एक निरंतर चयन क्वेरी योजना में यह लगातार स्कैन और लेफ्ट आउटर जॉइन कहां से आते हैं?


21

मेरे पास यह तालिका है:

CREATE TABLE [dbo].[Accounts] (
    [AccountId] UNIQUEIDENTIFIER UNIQUE NOT NULL DEFAULT NEWID(),
    -- WHATEVER other columns
);
GO
CREATE UNIQUE CLUSTERED INDEX [AccountsIndex]
    ON [dbo].[Accounts]([AccountId] ASC);
GO

यह प्रश्न:

DECLARE @result UNIQUEIDENTIFIER
SELECT @result = AccountId FROM Accounts WHERE AccountId='guid-here'

एक क्वेरी सूचकांक के साथ निष्पादित एक एकल सूचकांक सीक से - उम्मीद के मुताबिक:

SELECT <---- Clustered Index Seek

यह क्वेरी समान है:

DECLARE @result UNIQUEIDENTIFIER
SET @result = (SELECT AccountId FROM Accounts WHERE AccountId='guid-here')

लेकिन इसे एक योजना के साथ क्रियान्वित किया जाता है, जहां इंडेक्स सीक के परिणाम को छोड़ दिया जाता है, कुछ निरंतर स्कैन के परिणाम में शामिल हो जाता है और फिर गणना स्कैटर में खिलाया जाता है:

SELECT <--- Compute Scalar <--- Left Outer Join <--- Constant Scan
                                      ^
                                      |------Clustered Index Seek

वह अतिरिक्त जादू क्या है? लेफ्ट आउटर जॉइन के बाद वह लगातार स्कैन क्या करता है?

जवाबों:


29

दोनों कथनों के शब्दार्थ अलग-अलग हैं:

  • यदि कोई पंक्ति नहीं मिली है, तो पहला चर का मान निर्धारित नहीं करता है।
  • यदि कोई पंक्ति नहीं मिली है, तो दूसरा हमेशा चर सेट करता है, जिसमें अशक्त भी शामिल है।

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

का उपयोग करते हुए SELECT @result

-- Set initial value
DECLARE @result uniqueidentifier = {guid 'FE2CA909-1162-4C6C-A7AC-33B257E28539'};

-- @result does not change
SELECT @result = AccountId 
FROM Accounts 
WHERE AccountId={guid '7AD4D33C-1ED7-4183-B7F3-48C33D666525'};

SELECT @result;

परिणाम 1

का उपयोग करते हुए SET @result

-- Set initial value
DECLARE @result uniqueidentifier = {guid 'FE2CA909-1162-4C6C-A7AC-33B257E28539'};

-- @result set to null
SET @result = 
(
    SELECT AccountId 
    FROM Accounts 
    WHERE AccountId={guid '7AD4D33C-1ED7-4183-B7F3-48C33D666525'}
);

SELECT @result;

परिणाम २

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

असाइनमेंट का चयन करेंरूट नोड पर कोई पंक्ति नहीं आती है, इसलिए कोई असाइनमेंट नहीं होता है।

सेट का कामएक पंक्ति हमेशा रूट नोड पर आती है, इसलिए चर असाइनमेंट होता है।


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

वैरिएबल असाइनमेंट होने के लिए सब-वे से पंक्ति बनाने के लिए अन्य तरीके हैं। एक निरर्थक अदिश समुच्चय का उपयोग करना है (समूह द्वारा कोई समूह नहीं):

-- Set initial value
DECLARE @result uniqueidentifier = {guid 'FE2CA909-1162-4C6C-A7AC-33B257E28539'};

-- @result set to null
SET @result = 
    (
        SELECT MAX(AccountId)
        FROM Accounts 
        WHERE AccountId={guid '7AD4D33C-1ED7-4183-B7F3-48C33D666525'} 
    );
SELECT @result;

परिणाम 3

स्केलर कुल निष्पादन योजना

ध्यान दें कि स्केलर एग्रीगेट एक पंक्ति उत्पन्न करता है, भले ही उसे कोई इनपुट न मिले।

प्रलेखन:

यदि सेलेक्ट स्टेटमेंट में कोई पंक्तियाँ नहीं होती हैं, तो वेरिएबल अपने वर्तमान मूल्य को बनाए रखता है। यदि अभिव्यक्ति एक स्केलर सबक्वेरी है जिसका कोई मूल्य नहीं है, तो चर को NULL पर सेट किया जाता है।

चरों को निर्दिष्ट करने के लिए, हम अनुशंसा करते हैं कि आप SELECT @local_variable के बजाय SET @local_variable का उपयोग करें।

आगे की पढाई:

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