T-SQL में CAST का उपयोग करके प्रदर्शन हिट


12

हमारे पास एक SQL जनरेटर है जो SQL सशर्त कथनों को निर्दिष्ट क्षेत्रों (जो चर्चा के लिए: हम के रूप में लेबल करेंगे myField) के लिए उदारता से उत्सर्जित करते हैं ।

यदि myFieldइस प्रकार का है NVARCHAR, हम तो इस तरह की स्ट्रिंग के खिलाफ कहा क्षेत्र की तुलना कर सकते हैं: myField = 'foo'

हालांकि, यह प्रकार के क्षेत्रों के लिए काम नहीं करता है NTEXT। इस प्रकार, हमें एक कास्ट के साथ तुलना करना होगा CAST(myField as NVARCHAR(MAX)) = 'foo':। यह वास्तव में काम करेगा यदि myFieldप्रकार का है NVARCHARया NTEXT

पहले से ही टाइप की गई फ़ील्ड पर पूर्वोक्त कास्ट करने का प्रदर्शन क्या है NVARCHAR? मेरी आशा है कि एसक्यूएल सर्वर गतिशील रूप से पहचानने के लिए पर्याप्त स्मार्ट है जो myFieldपहले से ही प्रकार का है NVARCHAR(प्रभावी रूप CASTसे एक नो-ऑप में बदल रहा है )।


इस प्रश्न को खोजने वाले किसी भी व्यक्ति के लिए एक त्वरित नोट: NTEXT (और TEXT और IMAGE) को आधिकारिक तौर पर हटा दिया गया है और SQL सर्वर के कुछ भविष्य के संस्करण में हटा दिए जाने के कारण (हालांकि IIRC वे अभी भी SQL1014 में काम करते हैं), इसलिए आपको BARCHR (MAX) का उपयोग करना चाहिए (या VARCHAR (MAX) या VARBINARY (MAX)) के बजाय। इस उदाहरण में एक NVARCHAR (MAX) के साथ NTEXT कॉलम को बदलना कलाकारों की आवश्यकता को हटा देगा क्योंकि तुलना सीधे उस प्रकार से की जा सकती है, और यहां और अन्य संभावित दक्षता लाभ भी हैं। दुर्भाग्य से आप एक * (MAX) कॉलम को अनुक्रमणित नहीं कर सकते, लेकिन आप एक पाठ / NTEXT को या तो एक नहीं कर सकते।
डेविड स्पिललेट

जवाबों:


12

यदि स्तंभ की कास्ट बिलकुल एक ही प्रकार की लंबाई और लंबाई की है और शोधार्थी ढूंढता है तो यह शाब्दिक है कि वह इसकी अवहेलना करता है या इसे नो-ऑप के रूप में मानता है और समानता पर सूचकांक की तलाश करता है।

Seek Keys[1]: Prefix: [tempdb].[dbo].[#test].name = Scalar Operator(N'rpc')

यदि कॉलम का कास्ट एक ही डेटाटाइप पर है, लेकिन अधिक से अधिक लंबाई है और प्रीडिकेटेट एक स्ट्रिंग शाब्दिक है तो यह एक इंडेक्स स्कैन का कारण बनता है। यह स्पष्ट रूप से बचा जाना है।

यदि कॉलम का कास्ट एक ही डेटाटाइप और उसी या अधिक से अधिक लंबाई का है और प्रेडिकेटेट एक स्थानीय वैरिएबल है, तो यह एक कंपल्स स्केलर ऑपरेटर को निष्पादन योजना में जोड़ता है। यह GetRangeThroughConvertएक श्रेणी को कॉल और आउटपुट करता है।

इस रेंज का उपयोग इंडेक्स की तलाश में किया जाता है और यह काफी कुशल लगता है

Seek Keys[1]: 
Start: [tempdb].[dbo].[#test].name > Scalar Operator([Expr1006]), 
End: [tempdb].[dbo].[#test].name < Scalar Operator([Expr1007])

परीक्षण कोड

SELECT *
 INTO #test
  FROM [master].[dbo].[spt_values]

CREATE NONCLUSTERED INDEX [ixname] ON #test
(
    [name] ASC
)

DECLARE @name NVARCHAR(MAX)

SET @name = 'rpc'

SELECT name
FROM #test
WHERE CAST(name AS NVARCHAR(35))= @name --Cast the same and local variable

SELECT name
FROM #test
WHERE CAST(name AS NVARCHAR(MAX))=@name --Cast to longer and local variable

SELECT name
FROM #test
WHERE CAST(name AS NVARCHAR(35))='rpc' --Cast the same and literal

SELECT name
FROM #test
WHERE CAST(name AS NVARCHAR(MAX))='rpc' --Cast to longer and literal

6

सामान्य तौर पर, CASTप्रदर्शन को मार देगा क्योंकि यह मार्टिन स्मिथ के अंतिम उदाहरण शो के रूप में सूचकांक के किसी भी उपयोग को अमान्य करता है। nvarchar(max)एक अलग लंबाई पर या इसके लिए कास्टिंग करने का मतलब एक अलग डेटा प्रकार है: तथ्य यह है कि यह सब nvarcharअप्रासंगिक है।

उसके ऊपर, तुलनात्मक मामलों के दाहिने हाथ की ओर का डेटाटाइप भी है। यदि यह एक स्थानीय चर या एक अलग लंबाई का पैरामीटर है, तो एक पक्ष CAST2 डेटाटाइप्स के सबसे व्यापक रूप से अनुमानित होगा (देखें डेटाटाइप पूर्वता देखें )।

मूल रूप से, यदि आपके पास यह CASTकरने के लिए एक सामान्य है nvarchar(max), चीजों को बोलोगी। ntextइससे पहले कि मैं CASTसब कुछ जोड़कर उपयोग करने पर विचार करूं ।

रूपांतरण क्वेरी प्लान में नहीं दिखाया जा सकता है। देखें पॉल व्हाइट के ब्लॉग लेख


2

बस एक नोट, इस तरह से कास्टिंग करना जहां डेटक्रीटेड डेटटाइम है

 Cast (Datecreated as date) = cast(@MydatetimeValue as date)

यदि अनुक्रमणिका मौजूद है, तो अनुक्रमणिका का उपयोग करने के लिए SQL की क्षमता को नहीं तोड़ता है, और यदि वे मौजूद नहीं हैं, तो परिणामस्वरूप अनुपलब्ध अनुक्रमणिका लॉगिंग हो सकती है।

इसी प्रकार, जब से कास्टिंग intके लिए tinyintया bigintकरने के लिए intआदि, कच्चा समारोह एसक्यूएल अनुकूलक जानता है कि कलाकारों के आपरेशन 2 तुलनीय डेटाटाइप्स का सॉर्ट क्रम परिवर्तन नहीं करता है अनुक्रमित का उपयोग करने से रोक नहीं करता है।

यहां परीक्षण का एक समूह है, जिसे आप Adventureworks2008R2 का उपयोग करके चला सकते हैं और वास्तविक योजना देख सकते हैं

select count(*) from Sales.SalesOrderDetail where SalesOrderID = 8 --1
select top 10 * from Sales.SalesOrderDetail where cast(SalesOrderID as tinyint) = 8  --2
select top 10 * from Sales.SalesOrderDetail where cast(SalesOrderID as bigint) = 8  --3
select top 10 SalesOrderID from Sales.SalesOrderDetail where cast(ModifiedDate  as date) = '19780322' --4
select top 10 SalesOrderID from Sales.SalesOrderDetail where convert(date,ModifiedDate) = '19780322'  --5
select top 10 SalesOrderID from Sales.SalesOrderDetail where cast(ModifiedDate as varchar(20)) = '1978'  --6 -- THIS WILL NOT USE INDEX
select  SalesOrderID from Sales.SalesOrderDetail where cast(ModifiedDate  as date) between '19780101' and '19780109'  --7

1
तिथि के रूप में कास्ट एक इंडेक्स की तलाश कर सकता है, लेकिन अभी भी एक कास्ट के बिना रेंज की तलाश के रूप में व्यक्त करने की तुलना में समस्याएं हैं
मार्टिन स्मिथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.