SQL सर्वर के ऑप्टिमाइज़र किसी सम्मिलित तालिका में पंक्तियों की संख्या का अनुमान कैसे लगाता है?


13

मैं इस क्वेरी को AdventureWorks2012 डेटाबेस में चला रहा हूं :

SELECT 
    s.SalesOrderID,
    d.CarrierTrackingNumber,
    d.ProductID,
    d.OrderQty
FROM Sales.SalesOrderHeader s 
JOIN Sales.SalesOrderDetail d 
    ON s.SalesOrderID = d.SalesOrderID
WHERE s.CustomerID = 11077

यदि मैं अनुमानित निष्पादन योजना को देखता हूं, तो मैं निम्नलिखित देखता हूं:

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

प्रारंभिक सूचकांक की तलाश (शीर्ष दाएं) IX_SalesOrderHeader_CustomerID सूचकांक का उपयोग कर रहा है और शाब्दिक 11077 पर खोज कर रहा है। इसमें 2.6192 पंक्तियों का अनुमान है।

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

यदि मैं उपयोग करता हूं DBCC SHOW_STATISTICS ('Sales.SalesOrderHeader', 'IX_SalesOrderHeader_CustomerID') WITH HISTOGRAM, तो यह दर्शाता है कि 11077 का मूल्य दो सैंपल कीज़ 11019 और 11091 के बीच है।

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

11019 और 11091 के बीच अलग-अलग पंक्तियों की औसत संख्या 2.619718 है, या 2.61972 के लिए गोल है जो सूचकांक की तलाश के लिए दिखाई गई अनुमानित पंक्तियों का मूल्य है।

मैं जो हिस्सा नहीं समझता वह सेल्सऑडररेल टेबल के विरुद्ध क्लस्टर इंडेक्स की तलाश के लिए पंक्तियों की अनुमानित संख्या है।

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

अगर मैं चला DBCC SHOW_STATISTICS ('Sales.SalesOrderDetail', 'PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID'):

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

तो SalesOrderID (जिस पर मैं शामिल हो रहा हूं) का घनत्व 3.178134E-05 है। इसका मतलब है कि 1 / 3.178134E-05 (31465) SalesOrderDetail तालिका में अद्वितीय SalesOrderID मानों की संख्या के बराबर है।

यदि SalesOrderDetail में 31465 विशिष्ट SalesOrderID हैं, तो एक समान वितरण के साथ, SalesOrderID की पंक्तियों की औसत संख्या 121317 (कुल पंक्तियों की संख्या) 31465 से विभाजित होती है। औसत 3.85561 है।

इसलिए यदि पंक्तियों की अनुमानित संख्या 2.61972 है, और औसतन 3.85561 में लौटा जाना है, तो मुझे लगता है कि पंक्तियों की अनुमानित संख्या 2.61972 * 3.85561 = 10.10062 होगी।

लेकिन पंक्तियों की अनुमानित संख्या 11.4867 है।

मुझे लगता है कि दूसरे अनुमान की मेरी समझ गलत है और अलग-अलग संख्याओं से संकेत मिलता है। मैं क्या खो रहा हूँ?

जवाबों:


20

मुझे लगता है कि दूसरे अनुमान की मेरी समझ गलत है और अलग-अलग संख्याओं से संकेत मिलता है। मैं क्या खो रहा हूँ?

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

11.4867 संख्या (शोप्लां में प्रदर्शन के लिए) व्युत्पन्न आउटपुट की गणना अनुमानित कार्डिनैलिटी (30.0919) को पुनरावृत्तियों (2.61972) की संख्या से विभाजित करके निकाली गई है। परिणाम, एकल-सटीक फ्लोटिंग-पॉइंट अंकगणित का उपयोग करते हुए, 11.4867 है

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

SQL सर्वर 2012 और पहले में, चयन चयनात्मकता (एक पूरे के रूप में) SalesOrderIDप्रत्येक तालिका से हिस्टोग्राम का उपयोग करने का अनुमान है (प्रत्येक हिस्टोग्राम कदम के लिए गणना, आवश्यक के रूप में रैखिक प्रक्षेप का उपयोग करके सीमा सीमा संरेखण के बाद)। SalesOrderIDके साथ जुड़े हिस्टोग्राम SalesOrderHeaderटेबल भी स्वतंत्र की स्केलिंग प्रभाव के लिए निकाला जाता है CustomerIDफिल्टर।

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

साइड-नोट के रूप में, SQL सर्वर 2014 कार्डिनैलिटी अनुमानक स्वतंत्र-फ़िल्टर-समायोजित हिस्टोग्राम जानकारी ( "मोटे संरेखण" ) के संयोजन के लिए एक अलग दृष्टिकोण लेता है , जिसके परिणामस्वरूप इस क्वेरी के लिए 10.1006 पंक्तियों का एक अलग अंतिम अनुमान होता है :

Plan for computation:

  CSelCalcExpressionComparedToExpression
  (QCOL: [s].SalesOrderID x_cmpEq QCOL: [d].SalesOrderID)

Loaded histogram for column QCOL: [s].SalesOrderID from stats with id 1
Loaded histogram for column QCOL: [d].SalesOrderID from stats with id 1

Stats collection generated: 

  CStCollJoin(ID=4, **CARD=10.1006** x_jtInner)
      CStCollFilter(ID=3, CARD=2.61972)
          CStCollBaseTable(ID=1, CARD=31465 TBL: Sales.SalesOrderHeader AS TBL: s)
      CStCollBaseTable(ID=2, CARD=121317 TBL: Sales.SalesOrderDetail AS TBL: d)

यह प्रश्न में गणना के समान परिणाम के रूप में होता है, हालांकि विस्तृत तर्क भिन्न होता है (यानी यह एक मान्य नेस्टेड लूप कार्यान्वयन पर आधारित नहीं है)।

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