Perché SQL Server "Calcola scalare" quando seleziono una colonna calcolata persistente?


21

Le tre SELECTaffermazioni in questo codice

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;

genera questo piano:

progetto esecutivo

Perché il finale SELECT, che sta selezionando un valore persistente, genera un operatore di calcolo scalare ?


3
Vedi la risposta di @ SqlKiwi qui: Perché il piano di esecuzione include una chiamata di funzione definita dall'utente per una colonna calcolata che è persistente? . Nella tua query l'elenco delle colonne di output dalla tabella è solo [tempdb].[dbo].[persist_test].ide calcola il valore nonostante sia persistente.
Martin Smith,

Risposte:


14

Solo per riassumere i risultati sperimentali nei commenti, questo sembra essere un caso limite che si verifica quando si hanno due colonne calcolate nella stessa tabella, una persisted e una non persistente ed entrambe hanno la stessa definizione.

Nel piano per la query

SELECT id5p
FROM dbo.persist_test;

La scansione della tabella attiva persist_testemette solo la idcolonna. Il successivo scalare di calcolo si moltiplica per 5 e genera una colonna chiamata id5nonostante il fatto che questa colonna non sia nemmeno citata nella query. Lo scalare di calcolo finale prende il valore id5e lo emette come una colonna chiamataid5p .

Utilizzo dei flag di traccia spiegati in Deep Dive di Query Optimizer - Parte 2 (dichiarazione di non responsabilità: questi flag di traccia non sono documentati / non supportati) e osservano la query

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

Fornisce l'output

Albero prima della normalizzazione del progetto

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)

Albero dopo la normalizzazione del progetto

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

Quindi sembra che tutte le definizioni delle colonne calcolate vengano espanse poi durante la fase di normalizzazione del progetto tutte le espressioni identiche vengono ricondotte alle colonne calcolate e id5in questo caso sembra corrispondere . cioè non dà alcuna preferenza alla persistedcolonna.

Se la tabella viene ricreata con la seguente definizione

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

Quindi una richiesta per uno id5o id5psarà soddisfatta dalla lettura della versione persistente dei dati anziché fare il calcolo in fase di esecuzione in modo che la corrispondenza sembra avvenire (almeno in questo caso) in ordine di colonna.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.