実験結果をコメントにまとめると、これは同じテーブルに2つの計算列があり、1 persisted
つは保持されておらず、両方が同じ定義を持っている場合に発生するエッジケースのようです。
クエリの計画で
SELECT id5p
FROM dbo.persist_test;
テーブルスキャンpersist_test
はid
列のみを出力します。次のスカラーは、スカラーを5倍して計算id5
し、クエリでこの列が参照されていないにもかかわらず、呼び出された列を出力します。に沿った最後の計算スカラーは、の値を取り、id5
それをという列として出力しますid5p
。
クエリオプティマイザーの詳細-パート2(免責事項:これらのトレースフラグは文書化されていない/サポートされていない)で説明されているトレースフラグを使用し、クエリを確認する
SELECT id5,
id5p,
( id * 5 )
FROM dbo.persist_test
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8606);
出力を与える
プロジェクトの正規化前のツリー
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)
プロジェクトの正規化後のツリー
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
したがって、すべての計算列の定義が展開され、プロジェクトの正規化段階で、すべての同一の式が計算列に戻されid5
、この場合に一致するように見えます。つまり、persisted
列を優先しません。
次の定義でテーブルが再作成された場合
CREATE TABLE dbo.persist_test (
id INT NOT NULL
, id5p AS (5 * id) PERSISTED
, id5 AS (5 * id)
);
その後、いずれかの要求id5
またはid5p
マッチングを列順に(少なくともこの場合)が起こるように見えるように、データの永続化バージョンを読み取るのではなく、実行時に計算を行ってから満たされます。
[tempdb].[dbo].[persist_test].id
が保持され、永続化されているにもかかわらず値が計算されます。