क्यों sys.query_store_plan के साथ उन्मूलन कार्य में शामिल नहीं होता है?


10

निम्नलिखित क्वेरी स्टोर के साथ सामना की गई समस्या का सरलीकरण है:

CREATE TABLE #tears
(
    plan_id bigint NOT NULL
);

INSERT #tears (plan_id) 
VALUES (1);

SELECT
    T.plan_id
FROM #tears AS T
LEFT JOIN sys.query_store_plan AS QSP
    ON QSP.plan_id = T.plan_id;

plan_idस्तंभ की प्राथमिक कुंजी के रूप में दर्ज है sys.query_store_plan, लेकिन कार्य योजना लागू करके उपयोग नहीं करता है उन्मूलन में शामिल होने के रूप में उम्मीद होगी:

  1. डीएमवी की ओर से कोई विशेषता पेश नहीं की जा रही है।
  2. DMV प्राथमिक कुंजी plan_idअस्थायी तालिका से पंक्तियों की नकल नहीं कर सकती है
  3. LEFT JOINका उपयोग किया जाता है, इसलिए इससे कोई भी पंक्तियों को Tसमाप्त नहीं किया जा सकता है।

निष्पादन योजना

ग्राफिक की योजना बनाएं

यह क्यों है, और यहां उन्मूलन में शामिल होने के लिए क्या किया जा सकता है?

जवाबों:


16

प्रलेखन थोड़ा भ्रामक है। DMV एक गैर-भौतिक दृष्टिकोण है, और इस तरह की एक प्राथमिक कुंजी नहीं है। अंतर्निहित परिभाषा थोड़ी जटिल है, लेकिन इसकी एक सरलीकृत परिभाषा sys.query_store_planहै:

CREATE VIEW sys.query_store_plan AS
SELECT
    PPM.plan_id
    -- various other attributes
FROM sys.plan_persist_plan_merged AS PPM
LEFT JOIN sys.syspalvalues AS P
    ON P.class = 'PFT' 
    AND P.[value] = plan_forcing_type;

इसके अलावा, sys.plan_persist_plan_mergedयह भी एक दृश्य है, हालांकि इसकी परिभाषा को देखने के लिए समर्पित प्रशासक कनेक्शन के माध्यम से कनेक्ट करने की आवश्यकता है। फिर से, सरलीकृत:

CREATE VIEW sys.plan_persist_plan_merged AS   
SELECT     
    P.plan_id as plan_id,    
    -- various other attributes
FROM sys.plan_persist_plan P 
    -- NOTE - in order to prevent potential deadlock
    -- between QDS_STATEMENT_STABILITY LOCK and index locks   
    WITH (NOLOCK) 
LEFT JOIN sys.plan_persist_plan_in_memory PM
    ON P.plan_id = PM.plan_id;

इस पर अनुक्रमित sys.plan_persist_planहैं:

╔════════════════════════╦════════════════════════ ══════════════╦═════════════╗
║ index_name _ index_description key index_keys ║
╠════════════════════════╬════════════════════════ ══════════════╬═════════════╣
║ plan_persist_plan_cidx ered संकुल, अद्वितीय ARY योजना ║ योजना ers पर स्थित
║ plan_persist_plan_idx1 _ प्राथमिक - query_id (-) PR पर स्थित अस्पष्ट
╚════════════════════════╩════════════════════════ ══════════════╩═════════════╝

तो plan_idपर अद्वितीय होने के लिए विवश है sys.plan_persist_plan

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

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

DECLARE @t1 table (plan_id integer NOT NULL);
DECLARE @t2 table (plan_id integer NOT NULL UNIQUE CLUSTERED);
DECLARE @t3 table (plan_id integer NULL);

SELECT 
    T1.plan_id
FROM @t1 AS T1 
LEFT JOIN
(
    SELECT 
        T2.plan_id
    FROM @t2 AS T2
    LEFT JOIN @t3 AS T3 
        ON T3.plan_id = T2.plan_id
) AS Q1
    ON Q1.plan_id = T1.plan_id;

... जो उत्पादन में शामिल नहीं करता उन्मूलन:

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

समस्या के मूल में अधिकार प्राप्त करना, समस्या आंतरिक प्रश्न है:

DECLARE @t2 table (plan_id integer NOT NULL UNIQUE CLUSTERED);
DECLARE @t3 table (plan_id integer NULL);

SELECT 
    T2.plan_id
FROM @t2 AS T2
LEFT JOIN @t3 AS T3 
    ON T3.plan_id = T2.plan_id;

... स्पष्ट रूप से छोड़ दिया में शामिल होने से पंक्तियों में परिणाम हो सकता है @t2क्योंकि @t3कोई विशिष्टता बाधा नहीं है plan_id। इसलिए, इस निष्कासन को समाप्त नहीं किया जा सकता है:

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

इसे हल करने के लिए, हम ऑप्टिमाइज़र को स्पष्ट रूप से बता सकते हैं कि हमें किसी डुप्लिकेट plan_idमान की आवश्यकता नहीं है :

DECLARE @t2 table (plan_id integer NOT NULL UNIQUE CLUSTERED);
DECLARE @t3 table (plan_id integer NULL);

SELECT DISTINCT
    T2.plan_id
FROM @t2 AS T2
LEFT JOIN @t3 AS T3 
    ON T3.plan_id = T2.plan_id;

बाहरी जुड़ाव @t3अब समाप्त किया जा सकता है:

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

इसे वास्तविक क्वेरी पर लागू करना:

SELECT DISTINCT
    T.plan_id
FROM #tears AS T
LEFT JOIN sys.query_store_plan AS QSP
    ON QSP.plan_id = T.plan_id;

समान रूप से, हम इसके GROUP BY T.plan_idबजाय जोड़ सकते हैं DISTINCT। वैसे भी, आशावादी अब सही plan_idतरीके से नेस्टेड विचारों के माध्यम से सभी तरह की विशेषता के बारे में कारण बता सकते हैं , और वांछित रूप से दोनों बाहरी जोड़ को समाप्त कर सकते हैं:

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

ध्यान दें कि plan_idअस्थायी तालिका में अद्वितीय बनाना उन्मूलन में शामिल होने के लिए पर्याप्त नहीं होगा, क्योंकि यह गलत परिणाम नहीं देगा। हमें plan_idऑप्टिमाइज़र को यहां अपना जादू चलाने की अनुमति देने के लिए अंतिम परिणाम से स्पष्ट रूप से डुप्लिकेट मानों को अस्वीकार करना चाहिए ।

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