代码改变世界

【SQLServer】SQLServer执行计划运算符-第4部分

2022-10-01 13:47  abce  阅读(158)  评论(0编辑  收藏  举报

1.【SQLServer】SQLServer执行计划概览

2.【SQLServer】SQLServer执行计划的类型

3.【SQLServer】如何分析图形化的SQL执行计划

4.【SQLServer】SQLServer执行计划运算符-第1部分

5.【SQLServer】SQLServer执行计划运算符-第2部分

6.【SQLServer】SQLServer执行计划运算符-第3部分

 

创建一张表,并插入两千条记录用于本文测试:

CREATE TABLE ExPlanOperator_P4 (
  ID INT IDENTITY(1, 1)
  ,CX_Name VARCHAR(50)
  ,CX_PhoneNum VARCHAR(50)
  ,CX_Address VARCHAR(MAX)
  ,CX_Credit INT
  )
GO
 
INSERT INTO ExPlanOperator_P4
VALUES (
  'Alen'
  ,'9625788954'
  ,'London'
  ,500
  ) GO 1000
 
INSERT INTO ExPlanOperator_P4
VALUES (
  'Frank'
  ,'962445785'
  ,'Germany'
  ,1400
  ) GO 1000

 

SQL Server段运算符(Segment Operator)
SQL Server段运算符用于根据输入数据的值将输入数据分成不同的组。
假设我们运行以下SELECT语句,该语句使用ROW_NUMBER()排名函数对客户的信用进行排名:

SELECT ID
,CX_Name
,CX_PhoneNum
,CX_Address
,ROW_NUMBER() OVER (
PARTITION BY CX_Credit ORDER BY ID
)
FROM ExPlanOperator_P4;

从执行计划中可以看出,SQL Server引擎将从基础表中读取所有请求的数据,
根据Credit和ID值对这些值进行排序,然后使用Segment运算符将客户分组,具体取决于他们的Credit:

 

SQL Server表假脱机运算符(惰性假脱机)-Table Spool Operator (Lazy Spool)
SQL Server Lazy Spool用于在TempDB上构建一个临时表并以惰性方式填充它。换句话说,它仅在父运算符需要单独的行时才通过读取和存储数据来填充表。
假设我们运行以下查询,返回信用值大于所有客户平均信用的所有客户,使用返回平均信用值的子选择查询进行比较和过滤:

SELECT ID
,CX_Name
,CX_Credit
FROM ExPlanOperator_P4 CX1
WHERE CX_Credit > (
SELECT AVG(CX_Credit)
FROM ExPlanOperator_P4 CX2
WHERE CX1.ID = CX2.ID
)

  

SQL Server合并区间运算符(Merge Interval Operator)

SQL Server合并区间运算符用于通过识别重叠区间执行DISTINCT查询并将其合并以生成查询中没有重复谓词的非重叠区间,以避免多次扫描相同的值。

假设我们在ID列(包括Credit列)上创建索引后,运行以下SELECT语句,计算一组客户的Credit总和:​

CREATE INDEX IX_ID ON ExPlanOperator_P4 (ID) INCLUDE (CX_Credit)
 
DECLARE @CredID1 INT = 10
  ,@CredID2 INT = 20
  ,@CredID3 INT = 50
  ,@CredID4 INT = 70
  ,@CredID5 INT = 90
 
SELECT SUM(CX.CX_Credit)
FROM ExPlanOperator_P4 CX
WHERE ID IN (
    @CredID1
    ,@CredID2
    ,@CredID3
    ,@CredID4
    ,@CredID5
    )

从生成的SQL Server执行计划可以看出,SQL Server Engine是如何利用Merge Interval运算符来识别重复的,通过一次索引查找操作而不是两次查找相同的数据来加快数据比较和检索,如下图 :

 

SQL Server Filter运算符(Filter Operator)

SQL Server Filter运算符用于检查输入数据并仅返回满足谓词表达式的数据。运行以下SELECT 语句,返回重复credit的数量:​

SELECT COUNT(cx_credit)
FROM ExPlanOperator_P4
HAVING COUNT(cx_credit) > 5

从生成的执行计划中可以看到,SQL Server Engine在最后阶段使用了Filter运算符返回匹配HAVING子句谓词的记录:

 

SQL Server联机索引插入运算符(Online Index Insert Operator)
创建索引时,SQL Server支持在线创建或更改该索引,而不会阻止客户端在索引创建过程中连接到基础表。SQL Server在线索引插入运算符用于在线创建或更改索引。

假设我们运行下面的CREATE INDEX语句:

CREATE INDEX IX_ID ON ExPlanOperator_P4 (ID) INCLUDE (CX_Credit)
  WITH (
      DROP_EXISTING = ON
      ,ONLINE = ON
      )

生成的执行计划会告诉你,SQL Server Engine使用Online Index Insert操作符在线执行索引创建过程,而不会对基础表持有锁,如下所示:

 

SQL Server Sequence Project运算符
SQL Server Sequence Project运算符与Segment运算符最接近,在使用ROW_NUMBER()、RANK()或DENSE_RANK()窗口函数时可以看到。

SELECT ID
  ,CX_Name
  ,CX_PhoneNum
  ,CX_Address
  ,ROW_NUMBER() OVER (
    PARTITION BY CX_Credit ORDER BY ID
    )
FROM ExPlanOperator_P4;

生成的执行计划将展示Segment和Sequence Project之间的关系,其中Segments运算符将用于将排序的数据分类为组,Sequence Project运算符将控制完成当前组或开始计算新组, 如下所示:

 

SQL Server Eager Spool运算符

SQL Server Eager Spool运算符用于获取从另一个运算符传递给它的所有记录,一次读取所有数据,在一次读取期间阻止对数据的任何访问,并将其存储在tempdb数据库中的临时表中。

让我们删除之前在ID列上创建的索引,并将其替换为ID列上的聚集索引和cx_credit列上的非聚集索引,使用下面的脚本:​

DROP INDEX IX_ID ON ExPlanOperator_P4
 
CREATE CLUSTERED INDEX IX_NEWID ON ExPlanOperator_P4 (ID)
 
CREATE INDEX IX_CX_Credit ON ExPlanOperator_P4 (CX_Credit)

然后执行下面的UPDATE语句:

UPDATE ExPlanOperator_P4
SET cx_credit = cx_credit * 1.075
FROM ExPlanOperator_P4 WITH (INDEX = IX_CX_Credit)
WHERE cx_credit >= 900

执行计划将显示SQL Server引擎将在非聚集索引中寻找请求的数据,然后它将使用Eager Spool运算符从索引中读取数据并将其写入临时表,阻塞在读取过程中对该数据的访问,如下所示:

 

SQL Server并行运算符
SQL Server将设法使用并行计划来执行查询,以加速执行昂贵的查询。使用并行计划的决定取决于多种因素,
例如SQL Server是否安装在多处理器服务器上,是否满足请求的线程数,最大并行度选项未设置为1,并且查询的成本超过了先前配置的Cost Threshold for Parallelism值。
SQL Server使用Parallelism运算符执行该操作。假设我们运行下面的命令在表上重建高度碎片化的聚集索引:

ALTER INDEX IX_NEWID ON ExPlanOperator_P4 REBUILD

从生成的执行计划中看到,SQL Server引擎决定使用并行计划来加快执行该繁重查询的速度。从Parallelism运算符的存在中可以清楚地看出这一点,黄色箭头标识该运算符,如下所示:

 

本文地址:https://www.cnblogs.com/abclife/p/16703914.html