¿Por qué SQL Server "Compute Scalar" cuando SELECCIONO una columna calculada persistente?

21

Las tres SELECTdeclaraciones en este código

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;

generar este plan:

plan de ejecución

¿Por qué el final SELECT, que está seleccionando un valor persistente, genera un operador Compute Scalar ?

Nick Chammas
fuente
3
Vea la respuesta de @ SqlKiwi aquí: ¿Por qué el Plan de ejecución incluye una llamada a la función definida por el usuario para una columna calculada que persiste? . En su consulta, la lista de columnas de salida de la tabla es solo [tempdb].[dbo].[persist_test].idy calcula el valor a pesar de ser persistente.
Martin Smith

Respuestas:

14

Solo para resumir los hallazgos experimentales en los comentarios, este parece ser un caso marginal que ocurre cuando tiene dos columnas calculadas en la misma tabla, una persistedy una no persisten y ambas tienen la misma definición.

En el plan para la consulta

SELECT id5p
FROM dbo.persist_test;

La exploración de tabla persist_testsolo emite la idcolumna. El siguiente escalar de cálculo lo multiplica por 5 y genera una columna llamada a id5pesar del hecho de que esta columna ni siquiera está referenciada en la consulta. El escalar de cómputo final toma el valor de id5y lo genera como una columna llamada id5p.

Uso de los indicadores de seguimiento explicados en Query Optimizer Deep Dive - Parte 2 (descargo de responsabilidad: estos indicadores de seguimiento no están documentados / no son compatibles) y observa la consulta

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

Da la salida

Árbol antes de la normalización del proyecto

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)

Árbol después de la normalización del proyecto

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

Por lo tanto, parece que todas las definiciones de columnas calculadas se expanden y luego, durante la etapa de normalización del proyecto, todas las expresiones idénticas se vuelven a combinar con las columnas calculadas y, id5en este caso, coinciden . es decir, no le da preferencia a la persistedcolumna.

Si la tabla se vuelve a crear con la siguiente definición

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

Luego, una solicitud para cualquiera id5o id5pserá satisfecha al leer la versión persistente de los datos en lugar de hacer el cálculo en tiempo de ejecución, por lo que la coincidencia parece suceder (al menos en este caso) en el orden de las columnas.

Martin Smith
fuente