SQL सर्वर क्वेरी योजना के लिए अपनी अनुपलब्ध अनुक्रमणिका अनुशंसाओं में प्रमुख स्तंभों के क्रम को कैसे निर्धारित करता है?
SQL सर्वर क्वेरी योजना के लिए अपनी अनुपलब्ध अनुक्रमणिका अनुशंसाओं में प्रमुख स्तंभों के क्रम को कैसे निर्धारित करता है?
जवाबों:
जब SQL सर्वर किसी विशेष क्वेरी प्लान के लिए एक अनुपलब्ध इंडेक्स अनुशंसा बनाता है, तो यह संभावित कुंजी कॉलम को 2 समूहों में अलग करता है। पहले सेट में सभी अनुशंसित कॉलम शामिल हैं जो एक एक्वैलिटी प्रेडिकेट का हिस्सा हैं। दूसरे सेट में सभी अनुशंसित कॉलम शामिल हैं जो एक INEQUALITY की भविष्यवाणी का हिस्सा हैं।
प्रत्येक सेट के भीतर, स्तंभों की क्रमिक स्थिति के आधार पर तालिका की परिभाषा के आधार पर कॉलम का आदेश दिया जाता है।
(इस बात को साबित करने के लिए स्टैक ओवरफ्लो डेटाबेस के खिलाफ रेप्रो स्क्रिप्ट बनाने के लिए ब्रेंट ओज़र का बहुत धन्यवाद!)
1. 3 समान टेबल बनाएं , लेकिन उनके कॉलम अलग-अलग क्रम में रखें। (इसका कारण यह है कि स्तंभ के विभिन्न नामों और डेटाटिप्स का उपयोग यह दिखाने के लिए है कि अनुपलब्ध अनुक्रमणिका अनुशंसा में स्तंभ क्रम को प्रभावित नहीं करता है।)
CREATE TABLE dbo.NumberLetterDate (ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
fINT INT, fNVARCHAR NVARCHAR(40), fDATE DATETIME, AboutMe NVARCHAR(MAX));
GO
CREATE TABLE dbo.LetterDateNumber (ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
fNVARCHAR NVARCHAR(40), fDATE DATETIME, fINT INT, AboutMe NVARCHAR(MAX));
GO
CREATE TABLE dbo.DateNumberLetter (ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
fDATE DATETIME, fINT INT, fNVARCHAR NVARCHAR(40), AboutMe NVARCHAR(MAX));
GO
2. समान डेटा वाली तालिकाओं को आबाद करें। वास्तविक-विश्व डेटा वितरण के साथ उपयोगकर्ता तालिका से 100,000 पंक्तियाँ प्राप्त करें।
INSERT INTO dbo.NumberLetterDate(fINT, fNVARCHAR, fDATE, AboutMe)
SELECT TOP 100000 Age, DisplayName, LastAccessDate, AboutMe
FROM dbo.Users WITH (NOLOCK)
ORDER BY Id;
GO
INSERT INTO dbo.LetterDateNumber(fINT, fNVARCHAR, fDATE, AboutMe)
SELECT TOP 100000 Age, DisplayName, LastAccessDate, AboutMe
FROM dbo.Users WITH (NOLOCK)
ORDER BY Id;
GO
INSERT INTO dbo.DateNumberLetter(fINT, fNVARCHAR, fDATE, AboutMe)
SELECT TOP 100000 Age, DisplayName, LastAccessDate, AboutMe
FROM dbo.Users WITH (NOLOCK)
ORDER BY Id;
GO
3. एक प्रश्न लिखें, जिसमें सूचकांक की आवश्यकता हो। सभी 3 क्षेत्रों में सटीक मूल्य के लिए फ़िल्टरिंग, 3 समानता फ़िल्टर के साथ शुरू करें। ध्यान दें कि सभी 3 प्रश्नों के समान क्रम में एक ही फ़ील्ड हैं:
SELECT ID
FROM dbo.NumberLetterDate
WHERE fINT = 100
AND fNVARCHAR = 'Brent Ozar'
AND fDATE = '2018/01/01'
AND 1 = (SELECT 1);
SELECT ID
FROM dbo.LetterDateNumber
WHERE fINT = 100
AND fNVARCHAR = 'Brent Ozar'
AND fDATE = '2018/01/01'
AND 1 = (SELECT 1);
SELECT ID
FROM dbo.DateNumberLetter
WHERE fINT = 100
AND fNVARCHAR = 'Brent Ozar'
AND fDATE = '2018/01/01'
AND 1 = (SELECT 1);
GO
सभी तीन तालिकाओं में समान डेटा है, और क्वेरी समान हैं। एकमात्र अंतर फ़ील्ड ऑर्डर है - और हमारे लापता सूचकांक अनुरोधों में भी यही अंतर है:
निष्पादन योजनाओं में, अनुपलब्ध अनुक्रमणिका अनुरोध में स्तंभ क्रम तालिका में स्तंभ क्रम से बिल्कुल मेल खाता है। उदाहरण के लिए, dbo.NumberLetterDate में, संख्या स्तंभ पहले है, इसलिए यह अनुपलब्ध अनुक्रमणिका अनुरोध में भी सबसे पहले है:
इस तरह एकल-तालिका संचालन के लिए, अनुक्रमणिका फ़ील्ड क्रम चयनात्मकता, डेटाटाइप या क्वेरी में स्थिति पर निर्भर नहीं होता है। (अधिक जटिल प्रश्नों और जुड़ावों के साथ इसे साबित करने के लिए मैं इसे अन्य लोगों पर छोड़ता हूं।)
4. असमानता फिल्टर में मिलाएं। INT फ़ील्ड पर, उदाहरण के लिए, फ़िल्टर के रूप में <> 100 में डालें:
SELECT ID
FROM dbo.NumberLetterDate
WHERE fINT <> 100
AND fNVARCHAR = 'Brent Ozar'
AND fDATE = '2018/01/01'
AND 1 = (SELECT 1);
SELECT ID
FROM dbo.LetterDateNumber
WHERE fINT <> 100
AND fNVARCHAR = 'Brent Ozar'
AND fDATE = '2018/01/01'
AND 1 = (SELECT 1);
SELECT ID
FROM dbo.DateNumberLetter
WHERE fINT <> 100
AND fNVARCHAR = 'Brent Ozar'
AND fDATE = '2018/01/01'
AND 1 = (SELECT 1);
GO
निष्पादन योजनाओं में, समानता के क्षेत्र पहले जाते हैं, फिर असमानता के क्षेत्र - इसलिए, सभी 3 लापता सूचकांक अनुरोधों में अंतिम पता चलता है क्योंकि यह एक असमानता खोज है:
5. 3 असमानता फिल्टर का उपयोग करें। सभी फ़ील्ड के लिए समान खोज का उपयोग करें (<>):
SELECT ID
FROM dbo.NumberLetterDate
WHERE fINT <> 100
AND fNVARCHAR <> 'Brent Ozar'
AND fDATE <> '2018/01/01'
AND 1 = (SELECT 1);
SELECT ID
FROM dbo.LetterDateNumber
WHERE fINT <> 100
AND fNVARCHAR <> 'Brent Ozar'
AND fDATE <> '2018/01/01'
AND 1 = (SELECT 1);
SELECT ID
FROM dbo.DateNumberLetter
WHERE fINT <> 100
AND fNVARCHAR <> 'Brent Ozar'
AND fDATE <> '2018/01/01'
AND 1 = (SELECT 1);
GO
चूँकि कोई समानता खोज नहीं है, सभी 3 फ़ील्ड्स की अनुपलब्ध अनुक्रमणिका अनुशंसा में समान प्राथमिकता क्रम है, और अब हम फ़ील्ड क्रम से विशुद्ध रूप से छँटाई करने के लिए वापस आ गए हैं: