उपशम समानता का उपयोग क्यों करता है और इसमें शामिल नहीं होता है?


16

इस क्वेरी को चलाने के दौरान एसक्यूएल सर्वर समानांतरवाद का उपयोग क्यों करता है जो एक सबक्वेरी का उपयोग करता है लेकिन यह एक जॉइन का उपयोग करते समय नहीं करता है? जुड़ने का संस्करण धारावाहिक में चलता है और पूरा होने में लगभग 30 गुना अधिक समय लगता है।

संस्करण में शामिल हों: ~ 30secs

यहाँ छवि विवरण दर्ज करें

उपश्रेणी संस्करण: <1 सेकंड

यहाँ छवि विवरण दर्ज करें

संपादित करें: क्वेरी योजना के Xml संस्करण:

संस्करण में शामिल हों

संदिग्ध संस्करण

जवाबों:


12

जैसा कि टिप्पणियों में पहले से ही संकेत दिया गया है, जैसा कि आपको अपने आंकड़ों को अपडेट करने की आवश्यकता है।

पंक्तियों की अनुमानित संख्या बीच में से जुड़ती है locationऔर testrunsदोनों योजनाओं के बीच बेहद भिन्न होती है।

योजना के अनुमानों में शामिल हों: 1

योजना 1

उप क्वेरी योजना का अनुमान: 8,748

यहाँ छवि विवरण दर्ज करें

जुड़ने से निकलने वाली पंक्तियों की वास्तविक संख्या 14,276 है।

बेशक, यह बिल्कुल सहज ज्ञान युक्त नहीं है कि जुड़ने वाले संस्करण का अनुमान होना चाहिए कि 3 पंक्तियों से आना चाहिए locationऔर एकल सम्मिलित पंक्ति का उत्पादन करना चाहिए, जबकि उप क्वेरी का अनुमान है कि उन पंक्तियों में से एक ही जोड़ से 8,748 का उत्पादन होगा, लेकिन फिर भी मैं सक्षम था इसे पुन: पेश करने के लिए।

ऐसा तब होता है जब आंकड़े बनने पर हिस्टोग्राम के बीच कोई क्रॉस ओवर नहीं होता है। शामिल होने के संस्करण में एक पंक्ति होती है। और उप क्वेरी की एकल समानता एक अज्ञात चर के खिलाफ समानता की तलाश के रूप में एक ही अनुमानित पंक्तियों को मानती है।

वृषण की कार्डिनैलिटी है 26244। यह मानकर कि तीन अलग-अलग स्थान आईडी के साथ आबादी है, तो निम्नलिखित क्वेरी का अनुमान है कि 8,748पंक्तियों को वापस कर दिया जाएगा ( 26244/3)

declare @i int

SELECT *
FROM   testruns AS tr
WHERE  tr.location_id = @i

यह देखते हुए कि तालिका में locationsकेवल 3 पंक्तियाँ हैं, यह आसान है (यदि हम कोई विदेशी कुंजी नहीं मानते हैं) ऐसी स्थिति को रोकने के लिए जहां आँकड़े बनाए जाते हैं और फिर डेटा को इस तरह से बदल दिया जाता है कि नाटकीय रूप से खोई गई पंक्तियों की वास्तविक संख्या पर प्रभाव पड़ता है लेकिन अपर्याप्त है आँकड़ों के स्वत: अद्यतन यात्रा और दहलीज recompile।

जैसे-जैसे SQL सर्वर को इससे निकलने वाली पंक्तियों की संख्या मिलती है, वैसे-वैसे जुड़ने की गलत योजना में अन्य सभी पंक्ति अनुमानों को बड़े पैमाने पर कम करके आंका जाता है। साथ ही अर्थ है कि आप एक सीरियल प्लान प्राप्त करते हैं, क्वेरी को एक अपर्याप्त मेमोरी अनुदान भी मिलता है और सॉर्ट और हैश स्पिल में शामिल हो जाता है tempdb

एक संभावित परिदृश्य जो आपकी योजना में दिखाई गई वास्तविक बनाम अनुमानित पंक्तियों को पुन: पेश करता है, नीचे है।

CREATE TABLE location
  (
     id       INT CONSTRAINT locationpk PRIMARY KEY,
     location VARCHAR(MAX) /*From the separate filter think you are using max?*/
  )

/*Temporary ids these will be updated later*/
INSERT INTO location
VALUES      (101, 'Coventry'),
            (102, 'Nottingham'),
            (103, 'Derby')

CREATE TABLE testruns
  (
     location_id INT
  )

CREATE CLUSTERED INDEX IX ON testruns(location_id)

/*Add in 26244 rows of data split over three ids*/
INSERT INTO testruns
SELECT TOP (5984) 1
FROM   master..spt_values v1, master..spt_values v2
UNION ALL
SELECT TOP (5984) 2
FROM   master..spt_values v1, master..spt_values v2
UNION ALL
SELECT TOP (14276) 3
FROM   master..spt_values v1, master..spt_values v2

/*Create statistics. The location_id histograms don't intersect at all*/
UPDATE STATISTICS location(locationpk) WITH FULLSCAN;    
UPDATE STATISTICS testruns(IX) WITH FULLSCAN;

/* UPDATE location.id. Three row update is below recompile threshold*/
UPDATE location
SET    id = id - 100

फिर निम्नलिखित प्रश्नों को चलाने से वास्तविक अनुमानित विसंगति के समान अनुमान मिलता है

SELECT *
FROM   testruns AS tr
WHERE  tr.location_id = (SELECT id
                         FROM   location
                         WHERE  location = 'Derby')

SELECT *
FROM   testruns AS tr
       JOIN location loc
         ON tr.location_id = loc.id
WHERE  loc.location = ( 'Derby' ) 

यदि स्थान पर एक अद्वितीय बाधा जोड़ी जाती है, तो यह स्पष्ट हो जाता है कि "=" बिल्कुल एक पंक्ति में वापस आ जाएगा। फिर आपके उदाहरण में क्वेरी योजनाएं समान हो जाती हैं (स्कैन -> चाहता है): परिवर्तन तालिका स्थान में बाधा जोड़ें U_Location_Location अद्वितीय नॉनक्लेस्टर्ड (स्थान);
क्रोकेक

@ क्रोकुसेक हाँ। एहसास हुआ कि आपका बाद में क्या मतलब था और मेरी टिप्पणी को हटा दिया गया! क्या इससे जुड़ने वाले संस्करण के लिए पंक्तियों की अनुमानित संख्या में वृद्धि हो सकती है और साथ ही साथ उपकुंजी के समान भी हो सकती है? परीक्षण करने के लिए पीसी पर नहीं?
मार्टिन स्मिथ

@ क्रोकुसेक येप। सम्मिलित होने के समान अनुमान वाली पंक्तियाँ जैसे कि उस सिंगलटन मामले में उप क्वेरी के लिए दिखती हैं।
मार्टिन स्मिथ

हाँ। आइडेंटिकल क्वेरी प्लान, दोनों का अनुमान 8748 है, दोनों वास्तविक 14276 हैं। Btw, मैंने सोचा था कि locationId की प्री-कंप्यूटिंग उस अंतर को हल कर देगी लेकिन ऐसा नहीं होता है।
क्रुसेक

1
@ क्रोकुसेक - मैं अपने डीबी के भीतर स्थान और अन्य समान स्थानों के लिए अद्वितीय बाधा भी जोड़ूंगा। मुझे यह स्वीकार करना चाहिए कि मुझे यह पता नहीं चला कि इससे क्वेरी ऑप्टिमाइज़ेशन प्रभावित हुआ है। मैंने सोचा कि यह केवल डेटा अखंडता सुनिश्चित करने के लिए था। इस प्रश्न पर आपके इनपुट के लिए धन्यवाद।
क्रिस एल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.