यह लागत आधारित आशावादी का निर्णय है।
इस विकल्प में उपयोग की गई अनुमानित लागतें गलत हैं क्योंकि यह विभिन्न स्तंभों में मूल्यों के बीच सांख्यिकीय स्वतंत्रता को मानती है।
यह रो गोल गॉन दुष्ट में वर्णित मुद्दे के समान है जहां सम और विषम संख्या नकारात्मक रूप से सहसंबद्ध हैं।
प्रजनन करना आसान है।
CREATE TABLE dbo.animal(
id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
colour varchar(50) NOT NULL,
species varchar(50) NOT NULL,
Filler char(10) NULL
);
/*Insert 20 million rows with 1% black and 1% swan but no black swans*/
WITH T
AS (SELECT TOP 20000000 ROW_NUMBER() OVER (ORDER BY @@SPID) AS RN
FROM master..spt_values v1,
master..spt_values v2,
master..spt_values v3)
INSERT INTO dbo.animal
(colour,
species)
SELECT CASE
WHEN RN % 100 = 1 THEN 'black'
ELSE CAST(RN % 100 AS VARCHAR(3))
END,
CASE
WHEN RN % 100 = 2 THEN 'swan'
ELSE CAST(RN % 100 AS VARCHAR(3))
END
FROM T
/*Create some indexes*/
CREATE NONCLUSTERED INDEX ix_species ON dbo.animal(species);
CREATE NONCLUSTERED INDEX ix_colour ON dbo.animal(colour);
अब कोशिश करो
SELECT TOP 10 *
FROM animal
WHERE colour LIKE 'black'
AND species LIKE 'swan'
यह नीचे दी गई योजना है जिस पर खर्च किया गया है 0.0563167
।
योजना id
स्तंभ पर दो अनुक्रमितों के परिणामों के बीच एक मर्ज में शामिल होने में सक्षम है । ( मर्ज के अधिक विवरण यहां एल्गोरिदम में शामिल होते हैं )।
मर्ज ज्वाइन के लिए ज्वाइनिंग की के द्वारा दोनों इनपुट की आवश्यकता होती है।
गैर-अनुक्रमित अनुक्रमणिका द्वारा क्रमबद्ध किए जाते हैं (species, id)
और (colour, id)
क्रमशः (नॉनिक गैर गुच्छित अनुक्रमित में हमेशा पंक्ति लोकेटर जोड़ा जाता है जो कुंजी के अंत में निहित है यदि स्पष्ट रूप से जोड़ा नहीं गया है)। किसी भी वाइल्डकार्ड के बिना क्वेरी एक समानता की तलाश कर रही है species = 'swan'
और colour ='black'
। जैसा कि प्रत्येक चाहने वाले प्रमुख स्तंभ से केवल एक सटीक मान प्राप्त कर रहे हैं, id
इसलिए मिलान पंक्तियों का आदेश दिया जाएगा इसलिए यह योजना संभव है।
क्वेरी प्लान ऑपरेटर्स बाएं से दाएं निष्पादित करते हैं । बाएं ऑपरेटर से अपने बच्चों से पंक्तियों का अनुरोध किया जाता है, जो बदले में अपने बच्चों से पंक्तियों का अनुरोध करते हैं (और जब तक पत्ती के नोड्स तक नहीं पहुंच जाते हैं)। TOP
इटरेटर एक बार 10 प्राप्त किया गया है अपने बच्चे से अधिक पंक्तियां का अनुरोध बंद हो जाएगा।
एसक्यूएल सर्वर में सूचकांक पर आंकड़े हैं जो यह बताते हैं कि 1% पंक्तियाँ प्रत्येक विधेय से मेल खाती हैं। यह मानता है कि ये आँकड़े स्वतंत्र हैं (यानी या तो सकारात्मक या नकारात्मक रूप से सहसंबद्ध नहीं हैं) ताकि औसतन एक बार 1,000 पंक्तियों को संसाधित करने के बाद यह पहली विधेयकता से मेल खाता हो, यह 10 मिलान दूसरा मिल जाएगा और बाहर निकल सकता है। (वास्तव में ऊपर की योजना 1,000 के बजाय 987 दिखाती है लेकिन पर्याप्त रूप से बंद है)।
वास्तव में, जैसा कि विधेयकों को नकारात्मक रूप से सहसंबद्ध किया जाता है वास्तविक योजना यह दर्शाती है कि प्रत्येक अनुक्रमणिका से संसाधित होने के लिए आवश्यक सभी 200,000 मिलान पंक्तियों को शामिल किया गया है लेकिन इसे कुछ हद तक कम किया गया है क्योंकि शून्य शामिल पंक्तियों का अर्थ है कि शून्य लुकअप वास्तव में आवश्यक थे।
तुलना करना
SELECT TOP 10 *
FROM animal
WHERE colour LIKE 'black%'
AND species LIKE 'swan'
जो नीचे दी गई योजना को पूरा करता है 0.567943
अनुगामी वाइल्डकार्ड के जुड़ने से अब एक इंडेक्स स्कैन हुआ है। 20 मिलियन रो टेबल पर स्कैन के लिए योजना की लागत अभी भी काफी कम है।
querytraceon 9130
कुछ और जानकारी जोड़ना
SELECT TOP 10 *
FROM animal
WHERE colour LIKE 'black%'
AND species LIKE 'swan'
OPTION (QUERYTRACEON 9130)
यह देखा जा सकता है कि एसक्यूएल सर्वर यह अनुमान लगाता है कि उसे केवल १००,००० पंक्तियों को स्कैन करने की आवश्यकता होगी, क्योंकि यह १० विधेय से मेल खाता है और TOP
पंक्तियों का अनुरोध करना बंद कर सकता है।
फिर से यह स्वतंत्रता की धारणा के साथ समझ में आता है 10 * 100 * 100 = 100,000
अंत में कोशिश करते हैं और एक इंडेक्स चौराहे की योजना को मजबूर करते हैं
SELECT TOP 10 *
FROM animal WITH (INDEX(ix_species), INDEX(ix_colour))
WHERE colour LIKE 'black%'
AND species LIKE 'swan'
यह मेरे लिए 3.4625 की अनुमानित लागत के साथ एक समानांतर योजना देता है
यहां मुख्य अंतर यह है कि colour like 'black%'
विधेय अब कई अलग-अलग रंगों से मेल खा सकता है। इसका मतलब यह है कि उस विधेय के लिए मिलान सूचकांक पंक्तियों को अब क्रम में क्रमबद्ध किए जाने की गारंटी नहीं है id
।
उदाहरण के लिए, सूचकांक चाहने like 'black%'
वाले निम्नलिखित पंक्तियों को वापस कर सकते हैं
+------------+----+
| Colour | id |
+------------+----+
| black | 12 |
| black | 20 |
| black | 23 |
| black | 25 |
| blackberry | 1 |
| blackberry | 50 |
+------------+----+
प्रत्येक रंग के भीतर आईडी का आदेश दिया जाता है, लेकिन विभिन्न रंगों में आईडी अच्छी तरह से नहीं हो सकती हैं।
परिणामस्वरूप SQL सर्वर अब मर्ज ज्वाइन इंडेक्स चौराहे (बिना ब्लॉकिंग सॉर्ट ऑपरेटर को जोड़े) नहीं कर सकता है और इसके बजाय हैश ज्वाइन करने का विकल्प रखता है। हैश जॉइन बिल्ड इनपुट पर रोक लगा रहा है, इसलिए अब लागत इस तथ्य को दर्शाती है कि सभी मिलान पंक्तियों को बिल्ड इनपुट से संसाधित करने की आवश्यकता होगी, यह मानने के बजाय कि इसे पहली योजना के रूप में केवल 1,000 स्कैन करना होगा।
जांच इनपुट गैर अवरुद्ध है, लेकिन यह अभी भी गलत अनुमान लगाता है कि यह 987 पंक्तियों को संसाधित करने के बाद जांच को रोकने में सक्षम होगा।
(गैर-अवरोधक बनाम अवरुद्ध पुनरावृत्तियों पर आगे की जानकारी यहाँ)
अतिरिक्त अनुमानित पंक्तियों की बढ़ी हुई लागत को देखते हुए और हैश आंशिक रूप से क्लस्टर किए गए इंडेक्स स्कैन में शामिल होता है जो सस्ता दिखता है।
बेशक अभ्यास में "आंशिक" क्लस्टर इंडेक्स स्कैन आंशिक नहीं है और इसे योजनाओं की तुलना करते समय मान लिए गए 100 हजार के बजाय पूरे 20 मिलियन पंक्तियों के माध्यम से चुगना आवश्यक है।
के मूल्य में वृद्धि TOP
(या इसे पूरी तरह से हटा देना) अंततः एक टिपिंग बिंदु का सामना करता है जहां पंक्तियों की संख्या का अनुमान है कि सीआई स्कैन को कवर करने की आवश्यकता होगी, जिससे योजना अधिक महंगी दिखती है और यह सूचकांक चौराहे की योजना को प्रभावित करता है। मेरे लिए दो योजनाओं के बीच का कट ऑफ बिंदु TOP (89)
बनाम है TOP (90)
।
आपके लिए यह अच्छी तरह से भिन्न हो सकता है क्योंकि यह निर्भर करता है कि क्लस्टर इंडेक्स कितना चौड़ा है।
TOP
सीआई स्कैन को हटाने और मजबूर करना
SELECT *
FROM animal WITH (INDEX = 1)
WHERE colour LIKE 'black%'
AND species LIKE 'swan'
88.0586
मेरे उदाहरण तालिका के लिए मेरी मशीन पर खर्च किया गया है।
यदि SQL सर्वर को पता था कि चिड़ियाघर में कोई काला हंस नहीं है और इसे केवल 100,000 पंक्तियों को पढ़ने की बजाय एक पूर्ण स्कैन करने की आवश्यकता है, तो यह योजना नहीं चुनी जाएगी।
मैंने मल्टी कॉलम आँकड़े चालू करने animal(species,colour)
और animal(colour,species)
फ़िल्टर करने की कोशिश की है, animal (colour) where species = 'swan'
लेकिन इनमें से कोई भी यह समझाने में मदद नहीं करता है कि काले हंस मौजूद नहीं हैं और TOP 10
स्कैन को 100,000 से अधिक पंक्तियों को संसाधित करने की आवश्यकता होगी।
यह "समावेश धारणा" के कारण है जहां SQL सर्वर अनिवार्य रूप से मानता है कि यदि आप किसी ऐसी चीज की खोज कर रहे हैं जो संभवतः मौजूद है।
2008+ पर, पंक्तिबद्ध लक्ष्यों को बंद करने वाला एक प्रलेखित ट्रेस ध्वज 4138 है। इसका प्रभाव यह है कि योजना को इस धारणा के बिना लागत की जाती है कि TOP
बच्चे संचालकों को सभी मिलान पंक्तियों को पढ़े बिना जल्दी समाप्त करने की अनुमति देगा। इस ट्रेस ध्वज के साथ मैं स्वाभाविक रूप से अधिक इष्टतम सूचकांक प्रतिच्छेदन योजना प्राप्त करता हूं।
SELECT TOP 10 *
FROM animal
WHERE colour LIKE 'black%'
AND species LIKE 'swan'
OPTION (QUERYTRACEON 4138)
यह योजना अब दोनों इंडेक्स लाइक्स में पूरी 200 हजार पंक्तियों को पढ़ने के लिए सही तरीके से खर्च होती है, लेकिन लागतों में महत्वपूर्ण लुकअप (अनुमानित 2 हजार बनाम वास्तविक 0. यह TOP 10
अधिकतम 10 तक सीमित होगा लेकिन ट्रेस ध्वज इसे ध्यान में रखता है) । फिर भी योजना का चयन सीआई द्वारा पूर्ण सीआई स्कैन की तुलना में काफी सस्ता है।
बेशक यह योजना संयोजन जिसके लिए इष्टतम नहीं हो सकता है कर रहे हैं आम। जैसे कि सफेद हंस।
एक animal (colour, species)
आदर्श सूचकांक या आदर्श रूप animal (species, colour)
से क्वेरी दोनों परिदृश्यों के लिए अधिक कुशल होगी।
समग्र सूचकांक का सबसे कुशल उपयोग LIKE 'swan'
करने के लिए भी बदलना होगा = 'swan'
।
नीचे दी गई सारणी सभी चार क्रमपरिवर्तन के लिए निष्पादन योजनाओं में दिखाए गए विधेय और अवशिष्ट विधेयकों को दर्शाती है।
+----------------------------------------------+-------------------+----------------------------------------------------------------+----------------------------------------------+
| WHERE clause | Index | Seek Predicate | Residual Predicate |
+----------------------------------------------+-------------------+----------------------------------------------------------------+----------------------------------------------+
| colour LIKE 'black%' AND species LIKE 'swan' | ix_colour_species | colour >= 'black' AND colour < 'blacL' | colour like 'black%' AND species like 'swan' |
| colour LIKE 'black%' AND species LIKE 'swan' | ix_species_colour | species >= 'swan' AND species <= 'swan' | colour like 'black%' AND species like 'swan' |
| colour LIKE 'black%' AND species = 'swan' | ix_colour_species | (colour,species) >= ('black', 'swan')) AND colour < 'blacL' | colour LIKE 'black%' AND species = 'swan' |
| colour LIKE 'black%' AND species = 'swan' | ix_species_colour | species = 'swan' AND (colour >= 'black' and colour < 'blacL') | colour like 'black%' |
+----------------------------------------------+-------------------+----------------------------------------------------------------+----------------------------------------------+
TOP
एक चर में मूल्य का मतलब है कि यह मान लेंगेTOP 100
बजायTOP 10
। यह दोनों योजनाओं के बीच की टिपिंग बिंदु के आधार पर मदद कर सकता है या नहीं भी कर सकता है।