कॉनकैटेशन ऑपरेटर अपने इनपुट की तुलना में कम पंक्तियों का अनुमान क्यों लगाता है?


20

निम्नलिखित क्वेरी योजना स्निपेट में, यह स्पष्ट लगता है कि Concatenationऑपरेटर के लिए पंक्ति अनुमान होना चाहिए ~4.3 billion rows, या दो इनपुट के लिए पंक्ति अनुमानों का योग होना चाहिए ।

हालांकि, एक अनुमान का ~238 million rowsउत्पादन किया जाता है, जिससे एक उप-इष्टतम Sort/ Stream Aggregateरणनीति बनती है जो सैकड़ों जीबी डेटा को टेंपर्डब पर फैलता है। इस मामले में एक तार्किक रूप से सुसंगत अनुमान Hash Aggregateने स्पिल को हटा दिया और नाटकीय रूप से बेहतर प्रदर्शन किया।

यह SQL Server 2014 में एक बग है? क्या ऐसी कोई वैध परिस्थितियां हैं जिनमें इनपुट की तुलना में कम अनुमान उचित हो सकता है? क्या वर्कअराउंड उपलब्ध हो सकता है?

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

यहाँ पूर्ण क्वेरी योजना (अज्ञात) है। मेरे पास इस सर्वर तक sysadmin का उपयोग करने के लिए QUERYTRACEON 2363या समान ट्रेस झंडे से आउटपुट प्रदान करने के लिए नहीं है , लेकिन यदि वे सहायक होंगे तो इन आउटपुट को किसी व्यवस्थापक से प्राप्त करने में सक्षम हो सकते हैं।

डेटाबेस संगतता स्तर 120 में है, और इसलिए नए SQL Server 2014 कार्डिनैलिटी एस्टिमेटर का उपयोग कर रहा है।

हर बार डेटा लोड होने पर आँकड़े मैन्युअल रूप से अपडेट किए जाते हैं। डेटा की मात्रा को देखते हुए, हम वर्तमान में डिफ़ॉल्ट नमूना दर का उपयोग कर रहे हैं। यह संभव है कि उच्च नमूनाकरण दर (या FULLSCAN) का प्रभाव पड़ सकता है।

जवाबों:


21

इस कनेक्ट आइटम पर कैंपबेल फ्रेजर को उद्धृत करने के लिए :

ये "कार्डिनैलिटी असंगति" कई स्थितियों में उत्पन्न हो सकते हैं, जब समवर्ती का उपयोग किया जाता है। वे उत्पन्न हो सकते हैं क्योंकि अंतिम योजना में एक विशेष उपप्रकार का अनुमान एक अलग संरचित लेकिन तार्किक रूप से समतुल्य उपशीर्षक पर सुगंधित किया गया हो सकता है। कार्डिनैलिटी के आकलन की सांख्यिकीय प्रकृति के कारण, अलग-अलग लेकिन तार्किक रूप से बराबर पेड़ों पर अनुमान लगाने के लिए समान अनुमान प्राप्त करने की गारंटी नहीं है। तो कुल मिलाकर अपेक्षित स्थिरता की कोई गारंटी नहीं दी जाती है।

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

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

सभी ने कहा कि, SQL सर्वर 2014 में पेश किए गए नए कार्डिनैलिटी एस्टीमेटर (सीई) में कुछ विस्तृत बदलाव हुए हैं, जो मूल सीई के मामले में कुछ हद तक सामान्य बनाता है ।

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

अज्ञात योजना से विवरण का आकलन करना कठिन हो जाता है, लेकिन मैं बिटमैप पर भी ध्यान से देखूंगा कि क्या वे 'अनुकूलित' (Opt_Bitmap) या पोस्ट-ऑप्टिमाइज़ेशन (बिटमैप) किस्म के हैं। मुझे फिल्टर्स पर भी शक है।

यदि पंक्ति की गिनती कुछ भी सटीक है, तो यह एक क्वेरी की तरह प्रतीत होता है, जो कॉलमस्टोर से लाभान्वित हो सकती है। सामान्य लाभों से अलग, आप बैच मोड ऑपरेटरों के लिए गतिशील मेमोरी अनुदान का लाभ उठाने में सक्षम हो सकते हैं ( ट्रेस फ्लैग 9389 की आवश्यकता हो सकती है)।


7

SQL सर्वर 2012 (11.0.6020) पर एक समान रूप से सरल परीक्षण बिस्तर का निर्माण मुझे दो हैश मिलान वाले प्रश्नों के साथ एक योजना को फिर से बनाने की अनुमति देता है UNION ALL। मेरा परीक्षण-बिस्तर आपके द्वारा देखे गए गलत अनुमान को प्रदर्शित नहीं करता है। शायद यह है एक SQL सर्वर 2014 सीई समस्या।

मुझे एक क्वेरी के लिए 133.785 पंक्तियों का अनुमान है जो वास्तव में 280 पंक्तियों को लौटाता है, हालांकि उम्मीद की जानी है कि हम नीचे देखेंगे।

IF OBJECT_ID('dbo.Union1') IS NOT NULL
DROP TABLE dbo.Union1;
CREATE TABLE dbo.Union1
(
    Union1_ID INT NOT NULL
        CONSTRAINT PK_Union1
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , Union1_Text VARCHAR(255) NOT NULL
    , Union1_ObjectID INT NOT NULL
);

IF OBJECT_ID('dbo.Union2') IS NOT NULL
DROP TABLE dbo.Union2;
CREATE TABLE dbo.Union2
(
    Union2_ID INT NOT NULL
        CONSTRAINT PK_Union2
        PRIMARY KEY CLUSTERED
        IDENTITY(2,2)
    , Union2_Text VARCHAR(255) NOT NULL
    , Union2_ObjectID INT NOT NULL
);

INSERT INTO dbo.Union1 (Union1_Text, Union1_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;

INSERT INTO dbo.Union2 (Union2_Text, Union2_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;
GO

SELECT *
FROM dbo.Union1 u1
    INNER HASH JOIN sys.objects o ON u1.Union1_ObjectID = o.object_id
UNION ALL
SELECT *
FROM dbo.Union2 u2
    INNER HASH JOIN sys.objects o ON u2.Union2_ObjectID = o.object_id;

मुझे लगता है कि यह कारण दो परिणामी जोड़ियों के लिए आंकड़ों की कमी के आसपास है जो कि यूनिअनियन हैं। SQL सर्वर को आंकड़ों की कमी का सामना करने पर कॉलम की चयनात्मकता के आसपास अधिकांश मामलों में शिक्षित अनुमान लगाने की आवश्यकता होती है।

जो सैक ने यहां पर एक दिलचस्प पढ़ा है

ए के लिए UNION ALL, यह कहना सुरक्षित है कि हम संघ के प्रत्येक घटक द्वारा लौटी पंक्तियों की कुल संख्या देखेंगे, हालाँकि चूंकि SQL सर्वर दो घटकों के लिए पंक्ति अनुमान का उपयोग कर रहा है UNION ALL, हम देखते हैं कि यह दोनों से कुल अनुमानित पंक्तियों को जोड़ता है सहमति ऑपरेटर के लिए अनुमान के साथ आने के लिए प्रश्न।

उपरोक्त मेरे उदाहरण में, प्रत्येक भाग के लिए पंक्तियों की अनुमानित संख्या UNION ALL६६. the ९ २med है, जो कि जब १३३. we see५ के बराबर होती है, जिसे हम संघचालक के लिए पंक्तियों की अनुमानित संख्या के लिए देखते हैं।

यूनियन क्वेरी के लिए वास्तविक निष्पादन योजना इस प्रकार है:

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

आप पंक्तियों की "अनुमानित" बनाम "वास्तविक" संख्या देख सकते हैं। मेरे मामले में, दो हैश मैच ऑपरेटरों द्वारा लौटाई गई पंक्तियों की "अनुमानित" संख्या को जोड़ना परिचालनात्मक ऑपरेटर द्वारा दिखाई गई राशि के बराबर है।

मैं 2363 से ट्रेस से आउटपुट प्राप्त करने की कोशिश करूंगा, जैसा कि पॉल व्हाइट की पोस्ट में सुझाया गया है जो आप अपने प्रश्न में दिखा रहे हैं। वैकल्पिक रूप से, आप इस समस्या को "ठीक" करने के लिए यह देखने के लिए कि संस्करण 70 CE में वापस लौटने केOPTION (QUERYTRACEON 9481) लिए क्वेरी का उपयोग करने का प्रयास कर सकते हैं ।


1
धन्यवाद। मैंने यह निश्चित रूप से देखा है कि "कारण दोनों के लिए आंकड़ों की कमी के आसपास है जिसके परिणामस्वरूप संयुक्त हैं" बाद के जुड़ने या एकत्रीकरण पर एक बड़ा प्रभाव पड़ता है (जो कि UNION के बाद होता है)। SQL 2014 वास्तव में मेरे अनुभव में SQL 2012 से बेहतर है। यहाँ मैंने उदाहरण के लिए एक सरल परीक्षण स्क्रिप्ट का उपयोग किया है जो उदाहरण के लिए है: gist.github.com/anonymous/1497112d8b25ab8fb782a04569959c68 हालांकि, मुझे नहीं लगेगा कि किसी कॉनैटेटेन ऑपरेटर को मूल्यों के वितरण के बारे में समान जानकारी की आवश्यकता होगी जो एक जॉइन में शामिल हो। आवश्यकता हो सकती है।
ज्योफ पैटरसन

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