हिस्टोग्राम के बाहर कार्डिनैलिटी का अनुमान


14

सेट अप

मुझे कार्डिनैलिटी के अनुमान को समझने में थोड़ी परेशानी हो रही है। यहाँ मेरा परीक्षण सेटअप है:

  • स्टैक ओवरफ्लो डेटाबेस का 2010 संस्करण
  • SQL सर्वर 2017 CU15 + GDR (KB4505225) - 14.0.3192.2
  • नया CE (संगतता स्तर 140)

मैं इस proc है:

USE StackOverflow2010;
GO

CREATE OR ALTER PROCEDURE #sp_PostsByCommentCount
    @CommentCount int
AS
BEGIN
    SELECT * 
    FROM dbo.Posts p
    WHERE 
        p.CommentCount = @CommentCount
    OPTION (RECOMPILE); 
END;
GO

dbo.Postsटेबल पर कोई भी गैर-अनुक्रमित सूचकांक या आँकड़े नहीं हैं (कोई क्लस्टर किया गया सूचकांक है Id)।

इसके लिए एक अनुमानित योजना के लिए पूछने पर, "अनुमानित पंक्तियों" से बाहर आ रहा dbo.Postsहै 1,934.99:

EXEC #sp_PostsByCommentCount @CommentCount = 51;

जब मैंने अनुमानित योजना पूछी तो निम्नलिखित आँकड़े ऑब्जेक्ट स्वचालित रूप से बनाया गया था:

DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);

SSMS में सांख्यिकी आउटपुट का स्क्रीनशॉट

उस पर प्रकाश डाला गया हैं:

  • आंकड़ों में 1.81% (67,796 / 3,744,192) की कम नमूना दर है
  • केवल 31 हिस्टोग्राम चरणों का उपयोग किया गया था
  • "सभी घनत्व" मान है 0.03030303(33 अलग-अलग मूल्य नमूने थे)
  • RANGE_HI_KEYहिस्टोग्राम में अंतिम EQ_ROWS1 के साथ 50 है

सवाल

509 (2,147,483,647 तक) और 1,934.99 पंक्ति अनुमान में परिणाम से अधिक किसी भी मूल्य को पास करना। इस अनुमान को बनाने के लिए किस गणना या मूल्य का उपयोग किया जाता है? विरासत कार्डिनैलिटी का अनुमान लगाने वाला 1 पंक्ति का अनुमान लगाता है।

जो मैंने कोशिश की है

यहाँ कुछ सिद्धांत हैं, जो मैंने कोशिश की थी, या जानकारी के अतिरिक्त बिट्स जो मैं इसे देखने के दौरान खुदाई करने में सक्षम था।

घनत्व वेक्टर

मैंने शुरू में सोचा था कि यह घनत्व सदिश होगा, जैसा कि मैंने इस्तेमाल किया था OPTION (OPTIMIZE FOR UNKNOWN)। लेकिन इस आँकड़े ऑब्जेक्ट के लिए घनत्व वेक्टर 3,744,192 * 0.03030303 = 113,460 है, इसलिए यह नहीं है।

विस्तारित कार्यक्रम

मैंने एक विस्तारित ईवेंट सत्र चलाने की कोशिश की query_optimizer_estimate_cardinalityजिसने इस घटना को एकत्र किया (जो मुझे पॉल व्हाइट के ब्लॉग पोस्ट कार्डिनैलिटी एस्टिमेशन: कॉम्बिनेशन डेंसिटी स्टैटिस्टिक्स से पता चला ), और इस तरह के दिलचस्प टिडबेट्स मिले:

<CalculatorList>
  <FilterCalculator CalculatorName="CSelCalcColumnInInterval" Selectivity="-1.000" 
                    CalculatorFailed="true" TableName="[p]" ColumnName="CommentCount" />

  <FilterCalculator CalculatorName="CSelCalcAscendingKeyFilter" Selectivity="0.001" 
                    TableName="[p]" ColumnName="CommentCount" UseAverageFrequency="true" 
                    StatId="4" />
</CalculatorList>

तो ऐसा प्रतीत होता है कि CSelCalcAscendingKeyFilterकैलकुलेटर का उपयोग किया गया था (दूसरा कहता है कि यह विफल हो गया, जो भी इसका मतलब है)। यह कॉलम एक कुंजी, या अद्वितीय या आवश्यक रूप से आरोही नहीं है, लेकिन जो भी हो।

उस शब्द के कुछ Googling करने से मुझे कुछ ब्लॉग पोस्ट में ले जाया गया:

ये पोस्ट नए सीई आधारों को घनत्व वेक्टर के संयोजन और स्टेट के संशोधन काउंटर पर इन बाहरी-हिस्टोग्राम अनुमानों का संकेत देते हैं। दुर्भाग्य से, मैं पहले से ही घनत्व वेक्टर से इनकार कर चुका हूं (मुझे लगता है ?!), और संशोधन काउंटर शून्य (प्रति sys.dm_db_stats_propertiesभी) है।

ट्रेस झंडे

फॉरेस्ट ने सुझाव दिया कि मैं अनुमान प्रक्रिया के बारे में कुछ और जानकारी प्राप्त करने के लिए TF 2363 को चालू कर दूंगा। मुझे लगता है कि आउटपुट से सबसे प्रासंगिक बात यह है:

Plan for computation:

  CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)

Selectivity: 0.000516798

यह एक सफलता है (धन्यवाद, फॉरेस्ट!): उस 0.000516798संख्या (जो Selectivity="0.001"ऊपर XE विशेषता में अनपेक्षित रूप से गोल की गई है) को तालिका में पंक्तियों की संख्या से गुणा किया गया है वह अनुमान है जो मैं देख रहा हूं (1,934.99)।

मैं शायद कुछ स्पष्ट याद कर रहा हूं, लेकिन मैं इंजीनियर को रिवर्स करने में सक्षम नहीं हूं कि CSelCalcAscendingKeyFilterकैलकुलेटर के अंदर चयनात्मकता मूल्य कैसे उत्पन्न होता है ।

जवाबों:


13

मेरे परीक्षण के आधार पर, आउट-ऑफ-बाउंड कार्डिनैलिटी का अनुमान केवल पंक्ति गणना का वर्गमूल है, अंतिम आँकड़ों के अद्यतन के बाद से जोड़े गए पंक्तियों की संख्या से नीचे की ओर बँधा हुआ है, और प्रति मान औसत पंक्तियों द्वारा ऊपर की ओर बंधा हुआ है।

आपके मामले में, 1,934.99 = एसक्यूआरटी (3744192)

नीचे परीक्षण सेटअप:

--setup
USE TestDB
ALTER DATABASE [TestDB] SET AUTO_UPDATE_STATISTICS OFF
GO

DROP TABLE IF EXISTS dbo.Hist

CREATE TABLE dbo.Hist (
ID int identity primary key,
Num int
)

INSERT dbo.Hist
SELECT TOP 300
(ROW_NUMBER() OVER(ORDER BY(SELECT 1/0)))%3
FROM master..spt_values a
CROSS JOIN master..spt_values b
--Get estimated plan
--don't forget to run right after setup to auto-create stats
SELECT *
FROM dbo.Hist
WHERE Num = 1000
--gradually add rows, then rerun estimate above
INSERT dbo.Hist
SELECT TOP 100
-1
FROM master..spt_values a
--I sure hope you weren't testing this in prod (cleanup)
ALTER DATABASE [TestDB] SET AUTO_UPDATE_STATISTICS ON
GO

आश्चर्यजनक रूप से भी पंक्ति अनुमान इस दृष्टिकोण से उत्पन्न हुए थे: 20 कुल 400 पंक्तियों पर, 30 900 पर, 40 1600 में, आदि।

पिछले 10000, हालांकि, पंक्ति अनुमान अधिकतम 100 पर है, जो मौजूदा आंकड़ों में मूल्य प्रति पंक्तियों की संख्या है। केवल 10 पंक्तियों को जोड़ने से अनुमान 10 पर सेट हो जाएगा, क्योंकि sqrt (300)> 10।

इस प्रकार इस सूत्र का उपयोग करके अनुमान व्यक्त किया जा सकता है:

Estimate = MIN(SQRT(AC), MIN(AR, MC))

ध्यान दें कि यदि आँकड़ों का नमूना लिया जाता है, तो MC पर विचार नहीं किया जाता है। तो सूत्र बन जाता है:

Estimate = MIN(SQRT(AC), AR))

कहाँ पे

  • MC "संशोधन गणना" है (# संशोधनों के # बाद से आँकड़े बनाए गए थे)
  • एसी "समायोजित कार्डिनैलिटी" है (# सांख्यिकी और एमसी से पंक्तियों का #),
  • AR प्रति मान की औसत पंक्तियाँ हैं (स्तंभ में अलग-अलग मूल्यों से विभाजित आँकड़ों से # पंक्तियाँ)

इन अनुमानों के लिए सूत्र, और कैलकुलेटर के बारे में अन्य विवरण, इस ब्लॉग पोस्ट में पाए जा सकते हैं: CSelCalcAscendingKeyFilter कैलकुलेटर से अनुमानों का विश्लेषण

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