这段代码中的三个SELECT
语句
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;
生成这个计划:
为什么SELECT
选择持久值的 final 会生成计算标量运算符?
只是为了总结评论中的实验结果,这似乎是一个边缘情况,当您在同一个表中有两个计算列时发生,一个
persisted
和一个没有持久化并且它们都具有相同的定义。在查询计划中
表扫描
persist_test
仅发出id
列。下一个计算标量将其乘以 5 并输出一个名为的列,id5
尽管查询中甚至没有引用该列。最终的计算标量沿用 的值id5
并将其输出为名为 的列id5p
。使用Query Optimizer Deep Dive – Part 2中解释的跟踪标志(免责声明:这些跟踪标志未记录/不受支持)并查看查询
给出输出
项目规范化之前的树
项目规范化后的树
因此,似乎所有计算列定义都被扩展,然后在项目规范化阶段所有相同的表达式都匹配回计算列,并且在这种情况下恰好匹配
id5
。即它不给persisted
列任何优先权。如果使用以下定义重新创建表
id5
然后通过读取数据的持久版本而不是在运行时进行计算来满足对或将满足的请求,id5p
因此匹配似乎按列顺序发生(至少在这种情况下)。