यह क्वेरी इंडेक्स स्पूल का उपयोग क्यों नहीं करती है?


23

मैं यह प्रश्न पूछ रहा हूं ताकि ऑप्टिमाइज़र के व्यवहार को बेहतर ढंग से समझने और सूचकांक स्पूल के आसपास की सीमाओं को समझने के लिए। मान लीजिए कि मैंने पूर्णांक 1 से 10000 तक ढेर में डाल दिया है:

CREATE TABLE X_10000 (ID INT NOT NULL);
truncate table X_10000;

INSERT INTO X_10000 WITH (TABLOCK)
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

और एक नेस्टेड लूप के साथ मजबूर करें MAXDOP 1:

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);

यह SQL सर्वर की ओर ले जाने के लिए एक बल्कि अमित्र कार्रवाई है। जब दोनों तालिकाओं के पास कोई प्रासंगिक अनुक्रमणिका नहीं है, तो नेस्टेड लूप जॉइन अक्सर एक अच्छा विकल्प नहीं होता है। यहाँ योजना है:

बुरा प्रश्न है

क्वेरी मशीन स्पूल से प्राप्त 100000000 पंक्तियों के साथ मेरी मशीन पर 13 सेकंड लेती है। हालाँकि, मैं यह नहीं देखता कि क्वेरी को धीमा क्यों होना है। क्वेरी ऑप्टिमाइज़र में इंडेक्स स्पूल के माध्यम से फ्लाई पर इंडेक्स बनाने की क्षमता होती है । ऐसा लगता है कि यह सूचकांक स्पूल के लिए एक आदर्श उम्मीदवार होगा।

निम्न क्वेरी पहले वाले के समान परिणाम देती है, जिसमें एक इंडेक्स स्पूल होता है, और एक सेकंड से भी कम समय में समाप्त होता है:

SELECT *
FROM X_10000 a
CROSS APPLY (SELECT TOP (9223372036854775807) b.ID FROM X_10000 b WHERE a.ID = b.ID) ca
OPTION (LOOP JOIN, MAXDOP 1);

समाधान 1

इस क्वेरी में एक इंडेक्स स्पूल भी है और एक सेकंड से भी कम समय में खत्म होता है:

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID >= b.ID AND a.ID <= b.ID
OPTION (LOOP JOIN, MAXDOP 1);

समाधान 2

मूल क्वेरी में इंडेक्स स्पूल क्यों नहीं है? क्या प्रलेखित या अनिर्दिष्ट संकेत या झंडे के निशान का कोई सेट है जो इसे एक सूचकांक स्पूल देगा? मुझे यह संबंधित प्रश्न मिला , लेकिन यह मेरे प्रश्न का पूरी तरह से उत्तर नहीं देता है और मुझे इस क्वेरी के लिए रहस्यमय ट्रेस ध्वज नहीं मिल सकता है।

जवाबों:


20

जैसा कि आप जानते हैं, ऑप्टिमाइज़र की खोज संपूर्ण नहीं है। यह उन चीजों की कोशिश करता है जो संदर्भ में समझ में आता है, और जो अक्सर वास्तविक प्रश्नों पर लाभांश का भुगतान करते हैं। दो सिंगल-कॉलम अनइन्डेक्स हीप तालिकाओं के बीच एक लूप ज्वाइनिंग मजबूर करना ऐसा कोई परिदृश्य नहीं है। उस ने कहा, यहाँ कुछ विवरण हैं:

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

एक साधारण (गैर-लागू) जॉइन में बाहरी संदर्भों के बजाय ज्वाइन ऑपरेटर पर विधेय सम्मिलित होता है। एक गैर-लागू करने के लिए स्पूल अनुकूलन आमतौर पर एक आलसी टेबल स्पूल है, क्योंकि आंतरिक तरफ कोई विधेय नहीं है, केवल जुड़ने पर।

आशावादी एक आवेदन को सक्षम करने के लिए मक्खी पर एक सूचकांक बनाने पर विचार नहीं करता है; बल्कि घटनाओं का क्रम आम तौर पर उलटा होता है: एक अच्छा सूचकांक मौजूद होने के कारण इसे लागू करने के लिए बदलना।

आप कभी-कभी APPLYअपनी क्वेरी में सिंटैक्स का उपयोग करके शामिल होने के बजाय एक आवेदन को प्रोत्साहित कर सकते हैं । अविवादित ट्रेस ध्वज 9114 एक तार्किक लागू करने से एक अग्रिम अप में प्रवेश करने से ऑप्टिमाइज़र को नष्ट करके इसमें सहायता कर सकता है। उदाहरण के लिए:

SELECT * 
FROM dbo.X_1000 AS a
CROSS APPLY (SELECT * FROM dbo.X_1000 AS b WHERE b.ID = a.ID) AS b
OPTION (QUERYTRACEON 9114);

स्पूल योजना

एक इंडेक्स स्पूल को लागू करने के लिए इष्ट है क्योंकि बाहरी संदर्भ का अर्थ है चयन चयन में शामिल होने के अंदरूनी तरफ। आप अक्सर इसके माध्यम से देखेंगेSelToIndexOnTheFly लेकिन अन्य रास्ते मौजूद हैं। मेरा लेख ईगर इंडेक्स स्पूल और ऑप्टिमाइज़र देखें

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