As três SELECT
instruções neste 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;
gerar este plano:
Por que o final SELECT
, que está selecionando um valor persistente, gera um operador Compute Scalar ?
Apenas para resumir as descobertas experimentais nos comentários, este parece ser um caso extremo que ocorre quando você tem duas colunas computadas na mesma tabela, uma
persisted
e outra não persistida e ambas têm a mesma definição.No plano para a consulta
A varredura da tabela
persist_test
emite apenas aid
coluna. O próximo escalar de computação multiplica isso por 5 e gera uma coluna chamada,id5
apesar do fato de que essa coluna nem mesmo é referenciada na consulta. O escalar de computação final leva o valor deid5
e gera isso como uma coluna chamadaid5p
.Usando os sinalizadores de rastreamento explicados em Query Optimizer Deep Dive – Parte 2 (aviso: esses sinalizadores de rastreamento não são documentados/sem suporte) e examinam a consulta
Dá a saída
Árvore antes da normalização do projeto
Árvore após a normalização do projeto
Portanto, parece que todas as definições de colunas computadas são expandidas e, durante o estágio de normalização do projeto, todas as expressões idênticas são correspondidas de volta às colunas computadas e, por acaso, coincidem
id5
neste caso. ou seja, não dá preferência àpersisted
coluna.Se a tabela for recriada com a seguinte definição
Em seguida, uma solicitação para
id5
ouid5p
será atendida pela leitura da versão persistente dos dados, em vez de fazer o cálculo no tempo de execução, de modo que a correspondência pareça ocorrer (pelo menos neste caso) na ordem das colunas.