Dlaczego SQL Server „Compal Scalar”, kiedy wybieram utrwaloną kolumnę obliczeniową?


21

Trzy SELECTinstrukcje w tym kodzie

USE [tempdb];
GO

SET NOCOUNT ON;

CREATE TABLE dbo.persist_test (
      id            INT NOT NULL
    , id5           AS (id * 5)
    , id5p          AS (id * 5) PERSISTED
);

INSERT INTO dbo.persist_test (id)
VALUES (1), (2), (3);

SELECT id
FROM dbo.persist_test;

SELECT id5
FROM dbo.persist_test;

SELECT id5p
FROM dbo.persist_test;

DROP TABLE dbo.persist_test;

wygeneruj ten plan:

plan wykonania

Dlaczego finał SELECT, który wybiera utrwaloną wartość, generuje operator obliczania skalarnego ?


3
Zobacz odpowiedź @ SqlKiwi tutaj: Dlaczego plan wykonania zawiera zdefiniowane przez użytkownika wywołanie funkcji obliczanej kolumny, która jest utrwalona? . W zapytaniu lista kolumn wyjściowych z tabeli jest tylko [tempdb].[dbo].[persist_test].idi oblicza wartość pomimo utrwalenia.
Martin Smith

Odpowiedzi:


14

Podsumowując ustalenia eksperymentalne w komentarzach, wydaje się, że jest to przypadek skrajny, który występuje, gdy masz dwie kolumny obliczeniowe w tej samej tabeli, jedna persistedi jedna nie przetrwały i oba mają tę samą definicję.

W planie zapytania

SELECT id5p
FROM dbo.persist_test;

Skanowanie tabeli na persist_testemituje tylko idkolumnę. Następny obliczyć skalar wzdłuż mnoży to przez 5 i zwraca kolumnę wywoływaną, id5mimo że kolumna nie jest nawet przywoływana w zapytaniu. Końcowy skalar obliczeniowy wraz przyjmuje wartość id5i dane wyjściowe, które są nazywane kolumną id5p.

Korzystanie z flag śledzenia wyjaśnionych w Query Optimizer Deep Dive - Część 2 (zrzeczenie się: te flagi śledzenia są nieudokumentowane / nieobsługiwane) i przeglądanie zapytania

SELECT id5,
       id5p,
       ( id * 5 )
FROM   dbo.persist_test 
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8606);

Daje wynik

Drzewo przed normalizacją projektu

LogOp_Project

    LogOp_Get TBL: dbo.persist_test dbo.persist_test TableID=1717581157 TableReferenceID=0 IsRow: COL: IsBaseRow1002 

    AncOp_PrjList 

        AncOp_PrjEl QCOL: [tempdb].[dbo].[persist_test].id5

            ScaOp_Arithmetic x_aopMult

                ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id

                ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=5)

        AncOp_PrjEl QCOL: [tempdb].[dbo].[persist_test].id5p

            ScaOp_Arithmetic x_aopMult

                ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id

                ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=5)

        AncOp_PrjEl COL: Expr1004 

            ScaOp_Arithmetic x_aopMult

                ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id

                ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=5)

Drzewo po normalizacji projektu

LogOp_Project

    LogOp_Get TBL: dbo.persist_test dbo.persist_test TableID=1717581157 TableReferenceID=0 IsRow: COL: IsBaseRow1002 

    AncOp_PrjList 

        AncOp_PrjEl QCOL: [tempdb].[dbo].[persist_test].id5

            ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id5

        AncOp_PrjEl QCOL: [tempdb].[dbo].[persist_test].id5p

            ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id5

        AncOp_PrjEl COL: Expr1004 

            ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id5

Wygląda więc na to, że wszystkie obliczone definicje kolumn są rozszerzane, a następnie na etapie normalizacji projektu wszystkie identyczne wyrażenia są ponownie dopasowywane do kolumn obliczeniowych i id5w tym przypadku akurat się dopasowuje . tzn. nie daje pierwszeństwa persistedkolumnie.

Jeśli tabela zostanie ponownie utworzona z następującą definicją

CREATE TABLE dbo.persist_test (
      id            INT NOT NULL
    , id5p          AS (5 * id) PERSISTED
    , id5           AS (5 * id)
);

Następnie żądanie odczytu id5lub wykonania id5pbędzie spełnione po odczytaniu utrwalonej wersji danych zamiast przeprowadzaniu obliczeń w środowisku wykonawczym, więc dopasowanie wydaje się mieć miejsce (przynajmniej w tym przypadku) w kolejności kolumn.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.