मेरे पास क्या है, मेरे लिए, SARGability पर एक दिलचस्प सवाल। इस स्थिति में, यह दो दिनांक स्तंभों के बीच अंतर पर एक विधेय का उपयोग करने के बारे में है। यहाँ सेटअप है:
USE [tempdb]
SET NOCOUNT ON
IF OBJECT_ID('tempdb..#sargme') IS NOT NULL
BEGIN
DROP TABLE #sargme
END
SELECT TOP 1000
IDENTITY (BIGINT, 1,1) AS ID,
CAST(DATEADD(DAY, [m].[severity] * -1, GETDATE()) AS DATE) AS [DateCol1],
CAST(DATEADD(DAY, [m].[severity], GETDATE()) AS DATE) AS [DateCol2]
INTO #sargme
FROM sys.[messages] AS [m]
ALTER TABLE [#sargme] ADD CONSTRAINT [pk_whatever] PRIMARY KEY CLUSTERED ([ID])
CREATE NONCLUSTERED INDEX [ix_dates] ON [#sargme] ([DateCol1], [DateCol2])
जो मैं बार-बार देखूंगा, वह कुछ इस तरह है:
/*definitely not sargable*/
SELECT
* ,
DATEDIFF(DAY, [s].[DateCol1], [s].[DateCol2])
FROM
[#sargme] AS [s]
WHERE
DATEDIFF(DAY, [s].[DateCol1], [s].[DateCol2]) >= 48;
... जो निश्चित रूप से SARGable नहीं है। यह एक इंडेक्स स्कैन में परिणाम देता है, सभी 1000 पंक्तियों को पढ़ता है, अच्छा नहीं। अनुमानित पंक्तियाँ बदबू मारती हैं। आप इसे उत्पादन में कभी नहीं डालेंगे।
यह अच्छा होगा यदि हम सीटीई को अमल में ला सकते हैं, क्योंकि इससे हमें, अच्छी तरह से और अधिक प्रभावी, तकनीकी बोलने में मदद मिलेगी। लेकिन नहीं, हमें ऊपर की तरह ही निष्पादन योजना मिलती है।
/*would be nice if it were sargable*/
WITH [x] AS ( SELECT
* ,
DATEDIFF(DAY, [s].[DateCol1], [s].[DateCol2]) AS [ddif]
FROM
[#sargme] AS [s])
SELECT
*
FROM
[x]
WHERE
[x].[ddif] >= 48;
और हां, चूंकि हम स्थिरांक का उपयोग नहीं कर रहे हैं, इसलिए यह कोड कुछ भी नहीं बदलता है, और आधा SARGable भी नहीं है। कोई मज़ा नहीं। एक ही निष्पादन योजना।
/*not even half sargable*/
SELECT
* ,
DATEDIFF(DAY, [s].[DateCol1], [s].[DateCol2])
FROM
[#sargme] AS [s]
WHERE
[s].[DateCol2] >= DATEADD(DAY, 48, [s].[DateCol1])
यदि आप भाग्यशाली महसूस कर रहे हैं, और आप अपने कनेक्शन स्ट्रिंग्स में सभी एएनएसआई सेट विकल्पों का पालन कर रहे हैं, तो आप एक गणना कॉलम जोड़ सकते हैं, और उस पर खोज कर सकते हैं ...
ALTER TABLE [#sargme] ADD [ddiff] AS
DATEDIFF(DAY, DateCol1, DateCol2) PERSISTED
CREATE NONCLUSTERED INDEX [ix_dates2] ON [#sargme] ([ddiff], [DateCol1], [DateCol2])
SELECT [s].[ID] ,
[s].[DateCol1] ,
[s].[DateCol2]
FROM [#sargme] AS [s]
WHERE [ddiff] >= 48
यह आपको तीन प्रश्नों के साथ एक इंडेक्स की तलाश में मिलेगा। अजीब आदमी है जहाँ हम DateCol1 में 48 दिन जोड़ते हैं। साथ क्वेरी DATEDIFF
में WHERE
खंड, CTE
गणना स्तंभ पर विधेय के साथ, और अंतिम क्वेरी तुम सब बहुत अच्छे अनुमान के साथ एक बहुत अच्छे योजना सब देते हैं, और।
जो मुझे इस सवाल पर ले जाता है: एक ही प्रश्न में, क्या इस खोज को करने के लिए एक SARGable तरीका है?
कोई टेम्परेचर टेबल नहीं, कोई टेबल वैरिएबल नहीं, टेबल स्ट्रक्चर में कोई फेरबदल नहीं और न ही कोई नजारा।
मैं सेल्फ-जॉइन, सीटीई, सबक्वेरी या डेटा के साथ कई पास के साथ ठीक हूं। SQL सर्वर के किसी भी संस्करण के साथ काम कर सकते हैं।
गणना किए गए कॉलम से बचना एक कृत्रिम सीमा है क्योंकि मैं किसी अन्य चीज़ की तुलना में क्वेरी समाधान में अधिक रुचि रखता हूं।