Bu Sabit Tarama ve Sol Dış Birleştirme, önemsiz bir SELECT sorgu planında nereden geliyor?


21

Bu masam var:

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

Bu sorgu:

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

beklendiği gibi, tek bir Dizin Aramasından oluşan bir sorgu planı ile yürütülür -

SELECT <---- Clustered Index Seek

Bu sorgu aynı şeyi yapar:

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

ancak Index Seek sonucunun Dış Solda bırakıldığı bir planla yürütülür ve bazı Sabit Tarama sonucunda birleştirilir ve ardından Compute Scalar'a beslenir:

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

Bu ekstra büyü nedir? Sol Outer Join'in izlediği Constant Scan ne yapıyor?

Yanıtlar:


29

İki ifadenin anlambilimi farklıdır:

  • Bir satır bulunmazsa, ilki değişkenin değerini ayarlamaz.
  • İkincisi, hiçbir satır bulunmazsa null da dahil olmak üzere değişkeni daima ayarlar.

Sabit Tarama, temel tablodan hiçbir şey eşleşmezse değişkenin güncellenmesine neden olacak boş bir satır (sütunsuz!) Üretir. Sol birleştirme, boş sıranın birleşimden sağ çıkmasını sağlar. Değişken atama yürütme planının kök düğümünde olduğu düşünülebilir.

kullanma 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;

Sonuç 1

kullanma 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;

Sonuç 2

İcra planları

SELECT ödeviKök düğümde hiçbir satır gelmiyor, bu nedenle atama gerçekleşmiyor.

SET atamaKök düğümde her zaman bir satır gelir, bu nedenle değişken atama gerçekleşir.


Ekstra Sabit Tarama ve İç İçe Döngüler Sol Dış Birleştirme, endişelenecek bir şey değil. Özellikle birleşme, dış girişinde bir sıra ile ve iç girişinde en fazla bir sırayla (sizin örneğinizde) karşılaşmayı garanti ettiğinden ucuzdur.

Bir değişken atamasının gerçekleşmesini sağlamak için alt satırdan bir satırın oluşturulmasını sağlamanın başka yolları da vardır. Bunlardan biri, fazladan bir skaler agrega kullanmaktır (yan tümce tümce grubu):

-- 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;

Sonuç 3

Skaler toplam yürütme planı

Skaler agrega, girdi almasa bile bir satır oluşturduğuna dikkat edin.

Belgeler:

SELECT ifadesi satır döndürmezse, değişken bugünkü değerini korur. İfade, hiçbir değer döndürmeyen bir skalar alt sorgusu ise değişken NULL olarak ayarlanır.

Değişkenleri atamak için SELECT @local_variable yerine SET @local_variable kullanmanızı öneririz.

Daha fazla okuma:

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.