इन योजनाओं में एक अद्वितीय सूचकांक पर 1000 (एक ही) की अनुमानित लागत क्यों अलग है?


28

दोनों निष्पादन योजनाओं के नीचे दिए गए प्रश्नों में एक अद्वितीय सूचकांक पर 1,000 खोज करने का अनुमान है।

एक ही स्रोत तालिका पर एक ऑर्डर किए गए स्कैन द्वारा सीक को संचालित किया जाता है, इसलिए समान क्रम में समान मूल्यों की मांग करते हुए समाप्त होना चाहिए।

दोनों नेस्टेड लूप्स हैं <NestedLoops Optimized="false" WithOrderedPrefetch="true">

किसी को भी पता है कि इस कार्य की लागत पहली योजना में 0.172434 क्यों है, लेकिन दूसरे में 3.01702 है?

(प्रश्न का कारण यह है कि पहली क्वेरी मुझे स्पष्ट रूप से बहुत कम योजना लागत के कारण अनुकूलन के रूप में सुझाई गई थी। यह वास्तव में मुझे ऐसा लगता है जैसे यह अधिक काम करता है लेकिन मैं सिर्फ विसंगति को समझाने का प्रयास कर रहा हूं। ।)

सेट अप

CREATE TABLE dbo.Target(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL);

CREATE TABLE dbo.Staging(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL); 

INSERT INTO dbo.Target
SELECT TOP (1000000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1,  
     master..spt_values v2;

INSERT INTO dbo.Staging
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1;

प्रश्न 1 "योजना पेस्ट करें" लिंक

WITH T
     AS (SELECT *
         FROM   Target AS T
         WHERE  T.KeyCol IN (SELECT S.KeyCol
                             FROM   Staging AS S))
MERGE T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
  INSERT ( KeyCol, OtherCol )
  VALUES(S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
  UPDATE SET T.OtherCol = S.OtherCol;

प्रश्न 2 "योजना पेस्ट करें" लिंक

MERGE Target T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
  INSERT ( KeyCol, OtherCol )
  VALUES( S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
  UPDATE SET T.OtherCol = S.OtherCol; 

प्रश्न 1

प्रश्न २

SQL सर्वर 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64) पर उपरोक्त परीक्षण किया गया था


@ जोए ओबिश टिप्पणी में बताते हैं कि एक सरल रीप्रो होगा

SELECT *
FROM staging AS S 
  LEFT OUTER JOIN Target AS T 
    ON T.KeyCol = S.KeyCol;

बनाम

SELECT *
FROM staging AS S 
  LEFT OUTER JOIN (SELECT * FROM Target) AS T 
    ON T.KeyCol = S.KeyCol;

1,000 पंक्ति मेज़िंग टेबल के लिए उपरोक्त दोनों के पास अभी भी नेस्टेड लूप के साथ एक ही योजना का आकार है और व्युत्पन्न तालिका के बिना योजना सस्ती दिखाई देती है , लेकिन लागत में अंतर से ऊपर 10,000 राउंड मेज़िंग टेबल और एक ही लक्ष्य तालिका के लिए योजना में बदलाव नहीं करता है। आकार (एक पूर्ण स्कैन और मर्ज में शामिल है जो महंगे महंगे लुक की तुलना में अपेक्षाकृत अधिक आकर्षक लगता है) इस लागत की विसंगति को दिखाने के लिए योजनाओं की तुलना करना कठिन बनाने के अलावा अन्य निहितार्थ हो सकते हैं।

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

जवाबों:


21

किसी को भी पता है कि इस कार्य की लागत पहली योजना में 0.172434 क्यों है, लेकिन दूसरे में 3.01702 है?

सामान्यतया, एक नेस्टेड छोरों के नीचे एक आंतरिक पक्ष की तलाश एक यादृच्छिक I / O पैटर्न मानकर खर्च की जाती है। बाद की पहुंच के लिए एक सरल प्रतिस्थापन-आधारित कमी है, इस अवसर के लिए लेखांकन कि आवश्यक पृष्ठ को पहले से ही पुनरावृत्ति द्वारा स्मृति में लाया गया है। यह बुनियादी मूल्यांकन मानक (उच्च) लागत का उत्पादन करता है।

एक और कॉस्टिंग इनपुट है, स्मार्ट सीक कॉस्टिंग , जिसके बारे में बहुत कम जानकारी है। मेरा अनुमान (और यह सब इस स्तर पर है) यह है कि एसएससी आंतरिक पक्ष I / O लागत का अधिक विस्तार से आकलन करने का प्रयास करता है, शायद स्थानीय आदेश और / या मूल्यों की सीमा को ध्यान में रखकर। कौन जाने।

उदाहरण के लिए, पहली मांग वाला ऑपरेशन न केवल अनुरोधित पंक्ति में आता है, बल्कि उस पृष्ठ पर सभी पंक्तियों को (सूचकांक क्रम में)। समग्र अभिगम पैटर्न को देखते हुए, 1000 पंक्तियों को 1000 साइक्स में लाने के लिए केवल 2 भौतिक रीड की आवश्यकता होती है, यहां तक ​​कि रीड-फॉरवर्ड और प्रीफैचिंग अक्षम भी। उस दृष्टिकोण से, डिफ़ॉल्ट I / O लागत एक महत्वपूर्ण overestimate का प्रतिनिधित्व करता है, और SSC- समायोजित लागत वास्तविकता के करीब है।

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

यह दुर्भाग्यपूर्ण है कि अधीनस्थ बाहरी अनुमानों के लिए गणना स्केलर यहां एसएससी के साथ हस्तक्षेप करता है। गणना स्केलर आमतौर पर शामिल होने के ऊपर स्थानांतरित कर दिए जाते हैं, लेकिन इन लोगों को वहीं रहना पड़ता है जहां वे हैं। फिर भी, अधिकांश सामान्य गणना स्केल अनुकूलन के लिए बहुत पारदर्शी हैं, इसलिए यह थोड़ा आश्चर्य की बात है।

भले ही, जब PhyOp_Rangeएक इंडेक्स पर एक साधारण चयन से भौतिक ऑपरेशन का उत्पादन किया जाता है SelIdxToRng, तो एसएससी प्रभावी होता है। जब अधिक जटिल SelToIdxStrategy(एक सूचकांक रणनीति के लिए एक मेज पर चयन) नियोजित किया जाता है, जिसके परिणामस्वरूप PhyOp_Rangeएसएससी चलता है लेकिन कोई कमी नहीं होती है। फिर, ऐसा लगता है कि सरल, अधिक प्रत्यक्ष संचालन एसएससी के साथ सबसे अच्छा काम करते हैं।

काश, मैं आपको बता सकता कि एसएससी वास्तव में क्या करता है, और सटीक गणना दिखाता है, लेकिन मैं उन विवरणों को नहीं जानता। यदि आप अपने लिए उपलब्ध सीमित ट्रेस आउटपुट का पता लगाना चाहते हैं, तो आप 2398 में अवांछित ट्रेस ध्वज को नियोजित कर सकते हैं। एक उदाहरण आउटपुट है:

स्मार्ट की तलाश की लागत (7.1) :: 1.34078e + 154, 0.001

यह उदाहरण मेमो समूह 7, वैकल्पिक 1 से संबंधित है, जो एक ऊपरी सीमा को दर्शाता है, और 0.001 का कारक है। क्लीनर कारकों को देखने के लिए, समानता के बिना तालिकाओं को फिर से बनाना सुनिश्चित करें ताकि पृष्ठ यथासंभव घने हों। ऐसा किए बिना, कारक आपके उदाहरण लक्ष्य तालिका के लिए 0.000821 की तरह अधिक है। वहाँ कुछ काफी स्पष्ट रिश्ते हैं, ज़ाहिर है।

SSC को अनिर्दिष्ट ट्रेस ध्वज 2399 के साथ भी अक्षम किया जा सकता है। उस ध्वज के सक्रिय होने के साथ, दोनों लागतें उच्च मूल्य हैं।


8

यकीन नहीं होता कि यह एक उत्तर है लेकिन यह एक टिप्पणी के लिए थोड़ा लंबा है। अंतर का कारण मेरी ओर से शुद्ध अटकलें हैं और शायद दूसरों के लिए विचार के लिए भोजन हो सकता है।

निष्पादन योजनाओं के साथ सरल प्रश्न।

SELECT S.KeyCol, 
       S.OtherCol,
       T.*
FROM staging AS S 
  LEFT OUTER JOIN Target AS T 
    ON T.KeyCol = S.KeyCol;

SELECT S.KeyCol, 
       S.OtherCol,
       T.*
FROM staging AS S 
  LEFT OUTER JOIN (
                  SELECT *
                  FROM Target
                  ) AS T 
    ON T.KeyCol = S.KeyCol;

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

इन समतुल्य प्रश्नों के बीच मुख्य अंतर जो वास्तव में समान निष्पादन योजनाओं के परिणामस्वरूप हो सकता है, गणना स्केलर ऑपरेटर है। मुझे नहीं पता कि ऐसा क्यों होना चाहिए लेकिन मुझे लगता है कि जहां तक ​​आशावादी से व्युत्पन्न तालिका को अनुकूलित करने के लिए जा सकता है।

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

ऑप्टिमाइज़र के अंदर से : योजना लागत

सीपीयू लागत की गणना पहली पंक्ति के लिए 0.0001581 और बाद की पंक्तियों के लिए 0.000011 के रूप में की जाती है।
...
I / O की लागत 0.003125 बिल्कुल 1/320 है - मॉडल की धारणा को दर्शाती है कि डिस्क सबसिस्टम 320 यादृच्छिक I / O संचालन प्रति सेकंड कर सकता है
...
लागत घटक को पहचानने के लिए पर्याप्त स्मार्ट है। जिन पृष्ठों को डिस्क से लाने की आवश्यकता होती है, वे कभी भी पूरी तालिका को संग्रहीत करने के लिए आवश्यक पृष्ठों की संख्या से अधिक नहीं हो सकते।

मेरे मामले में तालिका में 5618 पृष्ठ हैं और 1000000 पंक्तियों से 1000 पंक्तियाँ प्राप्त करने के लिए आवश्यक पृष्ठों की संख्या 5.618 है जो 0.0156 की IO लागत दे रही है।

दोनों प्रश्नों के लिए सीपीयू लागत, एक ही हो तेजी 0.0001581 * 1000 executions = 0.1581

तो ऊपर दिए गए लेख के अनुसार हम पहली क्वेरी के लिए लागत की गणना 0.173725 कर सकते हैं।

और यह मानते हुए कि मैं इस बारे में सही हूं कि गणना स्केलर IO की गड़बड़ी कैसे कर रहा है, इसकी गणना 3.2831 तक की जा सकती है।

योजनाओं में जो दिखाया गया है, वैसा बिलकुल नहीं है, लेकिन पड़ोस में वहीं है।


6

(यह पॉल के जवाब के लिए एक टिप्पणी के रूप में बेहतर होगा, लेकिन मेरे पास अभी तक पर्याप्त प्रतिनिधि नहीं है।)

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

सबसे पहले, मैंने अंतिम मेमो पर एक नज़र डाली कि यह देखने के लिए कि भौतिक ऑपरेटरों का क्या उपयोग किया जा रहा था। वे निश्चित रूप से चित्रमय निष्पादन योजनाओं के अनुसार समान दिखते हैं। इसलिए, मैंने ट्रेस झंडे का उपयोग किया 3604और 8615, ग्राहक को पहला निर्देश उत्पादन और दूसरा अंतिम मेमो का खुलासा करता है:

SELECT S.*, T.KeyCol
FROM Staging AS S
      LEFT OUTER JOIN Target AS T
       ON T.KeyCol = S.KeyCol
OPTION(QUERYTRACEON 3604, -- Output client info
       QUERYTRACEON 8615, -- Shows Final Memo structure
       RECOMPILE);

पीछे से ट्रेसिंग Root Group, मुझे ये लगभग समान PhyOp_Rangeऑपरेटर मिले:

  1. PhyOp_Range 1 ASC 2.0 Cost(RowGoal 0,ReW 0,ReB 999,Dist 1000,Total 1000)= 0.175559(Distance = 2)
  2. PhyOp_Range 1 ASC 3.0 Cost(RowGoal 0,ReW 0,ReB 999,Dist 1000,Total 1000)= 3.01702(Distance = 2)

मेरे लिए एकमात्र स्पष्ट अंतर था- 2.0और 3.0, जो उनके संबंधित "ज्ञापन समूह 2, मूल" और "ज्ञापन समूह 3, मूल" को संदर्भित करता है। ज्ञापन की जाँच, ये एक ही बात को संदर्भित करते हैं - इसलिए अभी तक कोई मतभेद सामने नहीं आया है।

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

 SELECT S.*, T.KeyCol
 FROM Staging AS S
      LEFT OUTER JOIN Target AS T
        ON T.KeyCol = S.KeyCol
 OPTION (QUERYTRACEON 3604, -- Output info to client
         QUERYTRACEON 2363, -- Show stats and cardinality info
         QUERYTRACEON 8675, -- Show optimization process info
         QUERYTRACEON 8606, -- Show logical query trees
         QUERYTRACEON 8607, -- Show physical query tree
         QUERYTRACEON 2372, -- Show memory utilization info for optimization stages 
         QUERYTRACEON 2373, -- Show memory utilization info for applying rules
         RECOMPILE );

तीसरा, मैंने देखा PhyOp_Rangeकि हमारे नियमों के लिए कौन से नियम लागू होते हैं जो समान दिखते हैं। मैंने एक ब्लॉग पोस्ट में पॉल द्वारा उल्लेख किए गए युगल ट्रेस झंडे का इस्तेमाल किया ।

SELECT S.*, T.KeyCol
FROM Staging AS S
      LEFT OUTER JOIN (SELECT KeyCol
                      FROM Target) AS T
       ON T.KeyCol = S.KeyCol
OPTION (QUERYTRACEON 3604, -- Output info to client
        QUERYTRACEON 8619, -- Show applied optimization rules
        QUERYTRACEON 8620, -- Show rule-to-memo info
        QUERYTRACEON 8621, -- Show resulting tree
        QUERYTRACEON 2398, -- Show "smart seek costing"
        RECOMPILE );

आउटपुट से, हम देखते हैं कि JOINहमारे PhyOp_Rangeऑपरेटर को प्राप्त करने के लिए प्रत्यक्ष ने इस नियम को लागू किया है Rule Result: group=7 2 <SelIdxToRng>PhyOp_Range 1 ASC 2 (Distance = 2):। सबसिलेक्ट बजाय इस नियम लागू: Rule Result: group=9 2 <SelToIdxStrategy>PhyOp_Range 1 ASC 3 (Distance = 2)। यह वह जगह भी है जहां आप प्रत्येक नियम से जुड़ी "स्मार्ट सीक कॉस्टिंग" जानकारी देखते हैं। प्रत्यक्ष के लिए- JOINयह आउटपुट (मेरे लिए) है Smart seek costing (7.2) :: 1.34078e+154 , 0.001:। सबसिलेक्ट के लिए, यह आउटपुट है Smart seek costing (9.2) :: 1.34078e+154 , 1:।

अंत में, मैं बहुत निष्कर्ष नहीं निकाल सका - लेकिन पॉल का जवाब अधिकांश अंतर को बंद कर देता है। मैं स्मार्ट कॉस्टिंग पर कुछ और जानकारी देखना चाहता हूं।


4

यह वास्तव में एक जवाब नहीं है - जैसा कि मिकेल ने उल्लेख किया है, टिप्पणियों में इस समस्या पर चर्चा करना मुश्किल है ...

दिलचस्प बात यह है कि यदि आप सबक्विरी (select KeyCol FROM Target)को इनलाइन टीवीएफ में परिवर्तित करते हैं, तो आप योजना को देखते हैं, और इसकी लागत, साधारण मूल क्वेरी के समान है:

CREATE FUNCTION dbo.cs_test()
RETURNS TABLE
WITH SCHEMABINDING
AS 
RETURN (
    SELECT KeyCol FROM dbo.Target
    );

/* "normal" variant */
SELECT S.KeyCol, s.OtherCol, T.KeyCol 
FROM staging AS S 
    LEFT OUTER JOIN Target AS T ON T.KeyCol = S.KeyCol;

/* "subquery" variant */
SELECT S.KeyCol, s.OtherCol, T.KeyCol 
FROM staging AS S 
    LEFT OUTER JOIN (SELECT KeyCol FROM Target) AS T ON T.KeyCol = S.KeyCol;

/* "inline-TVF" variant */
SELECT S.KeyCol, s.OtherCol, T.KeyCol 
FROM staging AS S 
    LEFT OUTER JOIN dbo.cs_test() t ON s.KeyCol = t.Keycol

क्वेरी योजना ( पेस्टेटेप्लन लिंक ):

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

कटौती मुझे विश्वास दिलाती है कि लागत इंजन इस प्रकार के उप-वर्ग के संभावित प्रभाव के बारे में उलझन में है

उदाहरण के लिए, निम्नलिखित लें:

SELECT S.KeyCol, s.OtherCol, T.KeyCol 
FROM staging AS S 
    LEFT OUTER JOIN (
        SELECT KeyCol = CHECKSUM(NEWID()) 
        FROM Target
        ) AS T ON T.KeyCol = S.KeyCol;

आप कैसे खर्च करेंगे? क्वेरी ऑप्टिमाइज़र ऊपर के "सबक्वेरी" संस्करण के लिए एक समान योजना चुनता है, जिसमें एक संगणकीय स्केलर ( pastetheplan.com लिंक ) होता है:

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

गणना स्केलर के ऊपर दिखाए गए "सबक्वेरी" संस्करण से काफी भिन्न लागत है, हालांकि यह अभी भी एक अनुमान है क्योंकि क्वेरी ऑप्टिमाइज़र के पास जानने का कोई तरीका नहीं है, एक प्राथमिकता, क्या पंक्तियों की संख्या वापस हो सकती है। पंक्ति अनुमानों के अनजाने होने के कारण योजना बाएं बाहरी जोड़ के लिए हैश मैच का उपयोग करती है और इसलिए लक्ष्य तालिका में पंक्तियों की संख्या पर सेट होती है।

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

मेरे पास इससे बढ़िया निष्कर्ष नहीं है सिवाय इसके कि मैं मिकेल के जवाब में किए गए काम से सहमत हूं, और मुझे उम्मीद है कि कोई और बेहतर जवाब दे सकता है।

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