sql-server – 当我选择一个持久的计算列时,为什么SQL Server“Compute Scalar”?

前端之家收集整理的这篇文章主要介绍了sql-server – 当我选择一个持久的计算列时,为什么SQL Server“Compute Scalar”?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
代码中的三个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生成一个Compute Scalar运算符?

解决方法

只是为了总结评论中的实验结果,这似乎是一个边缘情况,当你在同一个表中有两个计算列时,一个持久化,一个不持久,并且它们都具有相同的定义.

查询计划中

SELECT id5p
FROM dbo.persist_test;

persist_test上的表扫描仅发出id列.下一个计算标量乘以5并输出一个名为id5的列,尽管该列甚至未在查询中引用.最终的计算标量采用id5的值,并将其输出为名为id5p的列.

使用Query Optimizer Deep Dive – Part 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,Value=5)

        AncOp_PrjEl COL: Expr1004 

            ScaOp_Arithmetic x_aopMult

                ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id

                ScaOp_Const TI(int,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

因此,似乎所有计算列定义都被扩展,然后在Project Normalization阶段期间,所有相同的表达式都匹配回计算列,在这种情况下它恰好匹配id5.即它没有给持久列提供任何偏好.

如果使用以下定义重新创建表

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

然后,通过读取持久化版本的数据而不是在运行时进行计算,将满足对id5或id5p的请求,因此匹配似乎按列顺序发生(至少在这种情况下).

猜你在找的MsSQL相关文章