यह क्वेरी मेरे गैर-अनुक्रमित सूचकांक का उपयोग क्यों नहीं कर रही है, और मैं इसे कैसे बना सकता हूं?


12

क्वेरी प्रदर्शन बढ़ाने के बारे में इस प्रश्न का अनुसरण करने के बाद , मैं यह जानना चाहूंगा कि क्या डिफ़ॉल्ट रूप से मेरे सूचकांक का उपयोग करने का कोई तरीका है।

यह क्वेरी लगभग 2.5 सेकंड में चलती है:

SELECT TOP 1000 * FROM [CIA_WIZ].[dbo].[Heartbeats]
WHERE [DateEntered] BETWEEN '2011-08-30' and '2011-08-31';

यह लगभग 33ms में चलता है:

SELECT TOP 1000 * FROM [CIA_WIZ].[dbo].[Heartbeats]
WHERE [DateEntered] BETWEEN '2011-08-30' and '2011-08-31' 
ORDER BY [DateEntered], [DeviceID];

[ID] फ़ील्ड (pk) पर एक संकुल सूचकांक है और [DateEntered], [DeviceID] पर एक गैर संकुल सूचकांक है। पहली क्वेरी क्लस्टर किए गए अनुक्रमणिका का उपयोग करती है, दूसरी क्वेरी मेरे गैर-संकुल अनुक्रमणिका का उपयोग करती है। मेरा प्रश्न दो भागों में है:

  • क्यों, चूंकि दोनों प्रश्नों में [DateEntered] फ़ील्ड पर WHERE क्लॉज है, क्या सर्वर पहले वाले पर क्लस्टर किए गए इंडेक्स का उपयोग करता है, लेकिन दूसरे का नहीं?
  • मैं बिना क्रम के भी इस क्वेरी पर डिफ़ॉल्ट रूप से गैर-संकुल सूचकांक का उपयोग कैसे कर सकता हूं? (या मैं ऐसा व्यवहार क्यों नहीं करना चाहूंगा?)

DateEntered एक DateTime है, इस मामले में मैं दिनांक भाग का उपयोग कर रहा हूँ, लेकिन मैं कभी-कभी दोनों दिनांक और समय के विरुद्ध एक साथ क्वेरी करता हूँ।
नैट

जवाबों:


9

पहली क्वेरी थ्रेशोल्ड पर आधारित एक टेबल स्कैन करती है, जिसे मैंने पहले समझाया था: क्या लाखों पंक्तियों के साथ एक संकीर्ण टेबल पर क्वेरी का प्रदर्शन बढ़ाना संभव है?

(सबसे अधिक संभावना है कि TOP 1000खंड के बिना आपकी क्वेरी 46k पंक्तियों पर अधिक वापस आ जाएगी। या कुछ जहां 35k और 46k के बीच; ग्रे क्षेत्र; ;-))

दूसरी क्वेरी, ऑर्डर की जानी चाहिए। जब से आप चाहते हैं कि आप जिस एनसी इंडेक्स का ऑर्डर दे रहे हैं, वह ऑप्टिमाइज़र के लिए उस इंडेक्स का उपयोग करने के लिए सस्ता है, और तब क्लस्टर इंडेक्स को स्कैन करने के लिए संकलित के रूप में लापता कॉलम को प्राप्त करने के लिए क्लस्टर इंडेक्स को बुकमार्क करने के लिए फिर से देखता है। उस आदेश के लिए।

ORDER BYखण्ड में स्तंभों के क्रम को उल्टा करें और जब आप NC INDEX के बाद बेकार हो जाएँ तो एक क्लस्टर इंडेक्स स्कैन पर वापस जाएँ।

अपने दूसरे प्रश्न का उत्तर भूल गए, कि आप ऐसा क्यों नहीं चाहते

नॉन क्लस्टर्ड नॉन कवरिंग इंडेक्स का उपयोग करने का मतलब है कि NC इंडेक्स में एक पंक्ति को देखा जाता है और फिर गुच्छित इंडेक्स में लापता कॉलम को देखना होता है (क्लस्टर इंडेक्स में टेबल के सभी कॉलम होते हैं)। IO की संकुलित अनुक्रमणिका में गुम कॉलम देखने के लिए यादृच्छिक IOs हैं।

यहाँ कुंजी रैंडम है। क्योंकि NC इंडेक्स में पाई जाने वाली प्रत्येक पंक्ति के लिए, एक्सेस विधियों को क्लस्टर इंडेक्स में एक नया पृष्ठ देखना होगा। यह यादृच्छिक है, और इसलिए बहुत महंगा है।

अब, दूसरी ओर ऑप्टिमाइज़र एक क्लस्टर इंडेक्स स्कैन के लिए भी जा सकता है। यह स्कैन रेंज को देखने के लिए आवंटन नक्शे का उपयोग कर सकता है और बड़े खंड में क्लस्टर इंडेक्स को पढ़ना शुरू कर सकता है। यह अनुक्रमिक और बहुत सस्ता है। (जब तक आपकी तालिका खंडित नहीं होती है :-)) नकारात्मक पक्ष यह है कि पूरे क्लस्टर सूचकांक को पढ़ने की आवश्यकता है। यह आपके बफ़र के लिए बुरा है और संभावित रूप से IOs की एक बड़ी मात्रा है। लेकिन फिर भी, अनुक्रमिक IOs।

आपके मामले में, ऑप्टिमाइज़र 35k और 46k पंक्तियों के बीच कहीं निर्णय लेता है, यह पूर्ण क्लस्टर इंडेक्स स्कैन के लिए कम खर्चीला है। हाँ, यह गलत है। और संकीर्ण गैर-संकुलित अनुक्रमणिका वाले बहुत से मामलों में WHEREउस मामले के लिए चयनात्मक खंड या बड़ी तालिका नहीं होने के कारण यह गलत हो जाता है। (आपकी तालिका बदतर है, क्योंकि यह एक बहुत ही संकीर्ण तालिका है।)

अब, ORDER BYयह पूर्ण क्लस्टर इंडेक्स को स्कैन करने के लिए और अधिक महंगा बनाता है और फिर परिणाम का आदेश देता है। इसके बजाय, ऑप्टिमाइज़र मानता है कि पहले से आदेशित NC इंडेक्स का उपयोग करना सस्ता है और फिर बुकमार्क लुक्स के लिए यादृच्छिक IO पेनल्टी का भुगतान करें।

तो आपके द्वारा आदेश एक सही "क्वेरी संकेत" प्रकार का समाधान है। लेकिन, एक निश्चित बिंदु पर, जब आपके क्वेरी परिणाम इतने बड़े होते हैं, तो बुकमार्क लुकअप रैंडम IOs के लिए जुर्माना इतना बड़ा होगा कि यह धीमा हो जाएगा। मुझे लगता है कि ऑप्टिमाइज़र उस बिंदु से पहले योजनाओं को वापस क्लस्टर इंडेक्स स्कैन में बदल देगा, लेकिन आप कभी भी निश्चित रूप से नहीं जानते हैं।

आपके मामले में, जब तक आपके आवेषण एंटरडेट द्वारा आदेशित किए जाते हैं, जैसा कि चैट में चर्चा की गई है और पिछले प्रश्न (लिंक देखें) आप एंटरडेट कॉलम पर क्लस्टर किए गए इंडेक्स बनाने के लिए बेहतर हैं।


20

अलग-अलग सिंटैक्स का उपयोग करके क्वेरी को व्यक्त करना कभी-कभी ऑप्टिमाइज़र को गैर-संकुल सूचकांक का उपयोग करने की आपकी इच्छा को संवाद करने में मदद कर सकता है। आपको नीचे दिए गए फॉर्म को ढूंढना चाहिए जो आप चाहते हैं:

SELECT
    [ID],
    [DeviceID],
    [IsPUp],
    [IsWebUp],
    [IsPingUp],
    [DateEntered]
FROM [dbo].[Heartbeats]
WHERE
    [ID] IN
(
    -- Keys
    SELECT TOP (1000)
        [ID]
    FROM [dbo].[Heartbeats]
    WHERE 
        [DateEntered] >= CONVERT(datetime, '2011-08-30', 121)
        AND [DateEntered]  < CONVERT(datetime, '2011-08-31', 121)
);

क्वेरी योजना

जब गैर-संकुल सूचकांक को संकेत के साथ मजबूर किया जाता है, तो उस योजना की तुलना करें:

SELECT TOP (1000) 
    * 
FROM [dbo].[Heartbeats] WITH (INDEX(CommonQueryIndex))
WHERE 
    [DateEntered] BETWEEN '2011-08-30' and '2011-08-31';

मजबूर सूचकांक संकेत योजना

योजनाएं अनिवार्य रूप से समान हैं (एक कुंजी लुकअप, क्लस्टर इंडेक्स पर तलाश से ज्यादा कुछ नहीं है)। दोनों योजना फॉर्म केवल कभी-कभी गैर-संकुलित सूचकांक पर एक की तलाश करेंगे और अधिकतम 1000 अनुक्रमणिका को संकुल सूचकांक में प्रदर्शित करेंगे।

महत्वपूर्ण अंतर शीर्ष ऑपरेटर की स्थिति में है। दो सीकों के बीच स्थित, शीर्ष ऑप्टिमाइज़र को क्लस्टर इंडेक्स के तार्किक-समतुल्य स्कैन के साथ दो मांगने वाले संचालन को बदलने से रोकता है। ऑप्टिमाइज़र समतुल्य रिलेशनल ऑपरेशंस के साथ लॉजिकल प्लान के कुछ हिस्सों को बदलकर काम करता है। शीर्ष एक संबंधपरक ऑपरेटर नहीं है, इसलिए पुनर्लेखन एक संकुल सूचकांक स्कैन में परिवर्तन को रोकता है। यदि ऑप्टिमाइज़र शीर्ष ऑपरेटर को पुन: भेजने में सक्षम था, तो यह अभी भी चाहत + तलाश पर स्कैन को तरजीह देगा क्योंकि लागत के आकलन के काम करने के तरीके।

स्कैन और कांटे की लागत

एक बहुत ही उच्च स्तर पर, स्कैन और स्पेक्स के लिए ऑप्टिमाइज़र की लागत मॉडल काफी सरल है: यह अनुमान है कि एक स्कैन में 1350 पृष्ठों को पढ़ने के रूप में 320 यादृच्छिक सीक्स की लागत है । यह शायद किसी विशेष आधुनिक I / O सिस्टम की हार्डवेयर क्षमताओं से कम समानता रखता है, लेकिन यह व्यावहारिक मॉडल के रूप में यथोचित काम करता है।

मॉडल भी कई सरल मान्यताओं को बनाता है, एक प्रमुख यह है कि हर क्वेरी को बिना किसी डेटा या इंडेक्स पेज के कैश में शुरू करने के लिए शुरू किया जाता है। निहितार्थ यह है कि प्रत्येक I / O का परिणाम शारीरिक I / O होगा - हालांकि यह शायद ही कभी व्यवहार में होगा। यहां तक ​​कि एक ठंडा कैश के साथ, पूर्व-लाने और पढ़ने-आगे का मतलब है कि जिन पृष्ठों की आवश्यकता होती है, वे वास्तव में स्मृति में होने की संभावना रखते हैं जब तक कि क्वेरी प्रोसेसर को उनकी आवश्यकता होती है।

एक और विचार यह है कि एक पंक्ति के लिए पहला अनुरोध जो मेमोरी में नहीं है, पूरे पृष्ठ को डिस्क से लाने का कारण होगा। एक ही पृष्ठ पर पंक्तियों के लिए अनुवर्ती अनुरोधों से शारीरिक I / O की संभावना नहीं होगी। कॉस्टिंग मॉडल में इस तरह के कुछ प्रभावों को लेने के लिए तर्क होते हैं, लेकिन यह सही नहीं है।

इन सभी चीजों (और अधिक) का मतलब है कि ऑप्टिमाइज़र शायद पहले की तुलना में स्कैन पर स्विच करना चाहता है। यादृच्छिक I / O केवल 'अनुक्रमिक' I / O की तुलना में 'बहुत अधिक महंगा' है अगर एक भौतिक ऑपरेशन परिणाम - स्मृति में पृष्ठों तक पहुंचना वास्तव में बहुत तेज है। यहां तक ​​कि जहां एक शारीरिक रीड की आवश्यकता होती है, स्कैन विखंडन के कारण अनुक्रमिक रीड में बिल्कुल भी परिणाम नहीं हो सकता है, और सीक को इस तरह से ढोया जा सकता है कि पैटर्न अनिवार्य रूप से अनुक्रमिक है। आधुनिक I / O प्रणालियों (विशेष रूप से ठोस-अवस्था) की बदलती प्रदर्शन विशेषता और संपूर्ण चीज़ बहुत ही अस्थिर लगने लगती है।

रो गोल

एक योजना में एक शीर्ष ऑपरेटर की उपस्थिति लागत दृष्टिकोण को संशोधित करती है। ऑप्टिमाइज़र यह जानने के लिए पर्याप्त स्मार्ट है कि स्कैन का उपयोग करके 1000 पंक्तियों को खोजने के लिए पूरे क्लस्टर इंडेक्स को स्कैन करने की आवश्यकता नहीं होगी - जैसे ही 1000 पंक्तियाँ मिली हैं, इसे रोक सकते हैं। यह शीर्ष ऑपरेटर पर 1000 पंक्तियों का एक 'पंक्ति लक्ष्य' निर्धारित करता है और यह अनुमान लगाने के लिए सांख्यिकीय जानकारी का उपयोग करता है कि पंक्ति स्रोत (इस मामले में एक स्कैन) से कितनी पंक्तियों की आवश्यकता है। मैंने इस गणना के विवरण के बारे में यहां लिखा है

इस उत्तर में छवियां SQL संतरी योजना एक्सप्लोरर का उपयोग करके बनाई गई थीं ।

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