加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

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

发布时间:2020-12-12 06:14:51 所属栏目:MsSql教程 来源:网络整理
导读:此代码中的三个SELECT语句 USE [tempdb];GOSET 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 idFROM dbo.persist_test;SELECT id5
此代码中的三个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的请求,因此匹配似乎按列顺序发生(至少在这种情况下).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读