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 persisted
i jedna nie przetrwały i oba mają tę samą definicję.
W planie zapytania
SELECT id5p
FROM dbo.persist_test;
Skanowanie tabeli na persist_test
emituje tylko id
kolumnę. Następny obliczyć skalar wzdłuż mnoży to przez 5 i zwraca kolumnę wywoływaną, id5
mimo że kolumna nie jest nawet przywoływana w zapytaniu. Końcowy skalar obliczeniowy wraz przyjmuje wartość id5
i 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 id5
w tym przypadku akurat się dopasowuje . tzn. nie daje pierwszeństwa persisted
kolumnie.
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 id5
lub wykonania id5p
bę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.
[tempdb].[dbo].[persist_test].id
i oblicza wartość pomimo utrwalenia.