यह सामान्य रूप से हल करने के लिए एक कठिन समस्या है, लेकिन कुछ चीजें हैं जो हम आशावादी को एक योजना चुनने में मदद करने के लिए कर सकते हैं। इस लिपि में 10,000 पंक्तियों के साथ एक तालिका बनाई गई है जिसमें पंक्तियों के ज्ञात छद्म यादृच्छिक वितरण के साथ वर्णन करना है:
CREATE TABLE dbo.SomeDateTable
(
Id INTEGER IDENTITY(1, 1) PRIMARY KEY NOT NULL,
StartDate DATETIME NOT NULL,
EndDate DATETIME NOT NULL
);
GO
SET STATISTICS XML OFF
SET NOCOUNT ON;
DECLARE
@i INTEGER = 1,
@s FLOAT = RAND(20120104),
@e FLOAT = RAND();
WHILE @i <= 10000
BEGIN
INSERT dbo.SomeDateTable
(
StartDate,
EndDate
)
VALUES
(
DATEADD(DAY, @s * 365, {d '2009-01-01'}),
DATEADD(DAY, @s * 365 + @e * 14, {d '2009-01-01'})
)
SELECT
@s = RAND(),
@e = RAND(),
@i += 1
END
पहला सवाल यह है कि इस तालिका को कैसे अनुक्रमित किया जाए। एक विकल्प DATETIMEकॉलम पर दो इंडेक्स प्रदान करना है, इसलिए ऑप्टिमाइज़र कम से कम यह चुन सकता है कि उसे तलाश करना है StartDateया नहीं EndDate।
CREATE INDEX nc1 ON dbo.SomeDateTable (StartDate, EndDate)
CREATE INDEX nc2 ON dbo.SomeDateTable (EndDate, StartDate)
स्वाभाविक रूप से, दोनों पर असमानताएं हैं StartDateऔर EndDateइसका मतलब है कि प्रत्येक सूचकांक में केवल एक स्तंभ उदाहरण क्वेरी में किसी खोज का समर्थन कर सकता है, लेकिन यह सबसे अच्छा है जो हम कर सकते हैं। हम INCLUDEएक कुंजी के बजाय प्रत्येक सूचकांक में दूसरा स्तंभ बनाने पर विचार कर सकते हैं, लेकिन हमारे पास अन्य प्रश्न हो सकते हैं जो अग्रणी स्तंभ पर एक समानता की तलाश कर सकते हैं और दूसरे कॉलम पर एक असमानता की तलाश कर सकते हैं। साथ ही, हमें इस तरह से बेहतर आंकड़े मिल सकते हैं। वैसे भी ...
DECLARE
@StartDateBegin DATETIME = {d '2009-08-01'},
@StartDateEnd DATETIME = {d '2009-10-15'},
@EndDateBegin DATETIME = {d '2009-08-05'},
@EndDateEnd DATETIME = {d '2009-10-22'}
SELECT
COUNT_BIG(*)
FROM dbo.SomeDateTable AS sdt
WHERE
sdt.StartDate BETWEEN @StartDateBegin AND @StartDateEnd
AND sdt.EndDate BETWEEN @EndDateBegin AND @EndDateEnd
यह क्वेरी चर का उपयोग करती है, इसलिए सामान्य तौर पर ऑप्टिमाइज़र चयनात्मकता और वितरण पर अनुमान लगाएगा, जिसके परिणामस्वरूप 81 पंक्तियों का एक कार्डिनैलिटी अनुमान है । वास्तव में, क्वेरी 2076 पंक्तियों का उत्पादन करती है, एक विसंगति जो अधिक जटिल उदाहरण में महत्वपूर्ण हो सकती है।
एसक्यूएल सर्वर 2008 SP1 CU5 या बाद में (या आर 2 आरटीएम CU1) पर हम का लाभ ले सकते पैरामीटर एम्बेडिंग अनुकूलन बेहतर अनुमान प्राप्त करने के लिए, बस जोड़कर OPTION (RECOMPILE)करने के लिए SELECTऊपर क्वेरी। यह बैच निष्पादित होने से ठीक पहले एक संकलन का कारण बनता है, जिससे SQL सर्वर वास्तविक पैरामीटर मानों को 'देख' सकता है और उन के लिए अनुकूलन कर सकता है। इस परिवर्तन के साथ, अनुमान 468 पंक्तियों में सुधार होता है (हालांकि आपको यह देखने के लिए रनटाइम योजना की जांच करने की आवश्यकता है)। यह अनुमान 81 पंक्तियों से बेहतर है, लेकिन फिर भी यह सब करीब नहीं है। ट्रेस ध्वज 2301 द्वारा सक्षम किए गए मॉडलिंग एक्सटेंशन कुछ मामलों में मदद कर सकते हैं, लेकिन इस क्वेरी के साथ नहीं।
समस्या यह है कि दो रेंजों द्वारा योग्य पंक्तियाँ ओवरलैप खोजती हैं। ऑप्टिमाइज़र की लागत और कार्डिनैलिटी आकलन घटक में किए गए सरल अनुमानों में से एक यह है कि विधेय स्वतंत्र हैं (इसलिए यदि दोनों में 50% की चयनात्मकता है, तो दोनों को लागू करने का परिणाम 50% = 25% पंक्तियों का 50% अर्हता प्राप्त करने के लिए माना जाता है। )। जहाँ इस तरह का सहसंबंध एक समस्या है, हम अक्सर इसके चारों ओर मल्टी-कॉलम और / या फ़िल्टर्ड आँकड़ों के साथ काम कर सकते हैं। अज्ञात प्रारंभ और अंत बिंदुओं वाली दो श्रेणियों के साथ, यह अव्यावहारिक हो जाता है। यह वह जगह है जहाँ हमें कभी-कभी क्वेरी का पुनर्लेखन करने के लिए एक ऐसे फॉर्म का सहारा लेना पड़ता है जो एक बेहतर अनुमान उत्पन्न करता है:
SELECT COUNT(*) FROM
(
SELECT
sdt.Id
FROM dbo.SomeDateTable AS sdt
WHERE
sdt.StartDate BETWEEN @StartDateBegin AND @StartDateEnd
INTERSECT
SELECT
sdt.Id
FROM dbo.SomeDateTable AS sdt
WHERE
sdt.EndDate BETWEEN @EndDateBegin AND @EndDateEnd
) AS intersected (id)
OPTION (RECOMPILE)
यह फॉर्म 2110 पंक्तियों (2076 वास्तविक बनाम) के रनटाइम अनुमान का उत्पादन करने के लिए होता है। जब तक आपके पास TF 2301 है, जिस स्थिति में अधिक उन्नत मॉडलिंग तकनीक चाल के माध्यम से देखते हैं और पहले की तरह ही अनुमान लगाते हैं: 463 पंक्तियाँ।
एक दिन SQL सर्वर अंतराल के लिए मूल समर्थन प्राप्त कर सकता है। यदि यह अच्छे सांख्यिकीय समर्थन के साथ आता है, तो डेवलपर्स इस तरह से ट्यूनिंग क्वेरी योजनाओं को थोड़ा कम कर सकते हैं।