常用执行计划操作符

一、数据访问操作符

1、SCAN操作符:扫描操作主要分为3种

Table Scan:当针对一个表(没有聚集索引、堆表)执行一个查询语句时,

此时将会做全表扫描操作(如果有where子句,则先执行全表扫描操作,然后在针对结果集做Filter操作)

示例:

Cluster Index Scan:聚集索引扫描,表中所有的数据都存在于聚集索引的叶节点中,因此聚集索引扫描相当于将整个表中的数据都取出。

Non-clustered Index Scan:当查询的字段都被包含在一个覆盖索引中的情况下,查询优化器会优先使用Index Scan来查找这些数据,

因为非聚集索引比聚集索引占用的空间小,I/O成本更低。

示例:在Test表上创建一个覆盖索引  

Create index idx_Name_IdentityNo_Sex_Age_Job_LiveAddress on Test(Name) INCLUDE(Sex,IdentityNo,Age,LiveAddress,Job)

查询SQL

SELECT Name,Sex,IdentityNo,Age,LiveAddress,Job FROM dbo.Test

执行计划如下

2、SEEK操作符:

根据索引的不同可以分为:聚集索引查询非聚集索引查找

聚集索引查找发生在对聚集索引字段(一般情况下都是主键字段)进行where过滤的情况下

非聚集索引查找发生在对非聚集索引字段进行where过滤的情况下

3、Bookmark Lookup操作符:书签查找发生在非聚集索引的语句中,用于查询不包含在当前索引中的字段

一般优化手段是将额外的字段包含在一个Include索引

二、连接操作符

1、Nested Loop

一般外表为小表(一般小于10000数据),较大数据表做为内表。循环嵌套连接查找内部循环表的次数等于外部循环的行数,

因此最好对内表的相应的字段上建索引,否则内表将需要做多次的全表扫描,性能有可能会产生影响。

2、Merge Join

 一般而言,当输入两端有序的情况下,适用Merge Join效率会比较高。

示例:b表中的ProductID上有建索引,此时输入两端都处于有序状态

SELECT  b.SalesOrderDetailID,a.Name FROM Production.Product a
JOIN Sales.SalesOrderDetail b ON a.ProductID=b.ProductID

如果输入两端处于无序的情况下,强制使用Merge Join连接,则将会额外多出排序操作以确保输入两端有序

SELECT  b.SalesOrderDetailID,a.Name FROM Production.Product a
INNER MERGE JOIN Sales.SalesOrderDetail b ON a.ListPrice=b.UnitPrice
WHERE a.ListPrice>5

3、Hash Join

 当连接表数据量较大,并且输入两端无序(连接列无索引)时,查询优化器将优先使用Hash Join连接方式

SELECT  b.SalesOrderDetailID,a.Name FROM Production.Product a
INNER JOIN Sales.SalesOrderDetail b ON a.ListPrice=b.UnitPrice

三、聚合操作符

聚合操作分两类:Stream Aggregate(流聚合)和Hash Aggregate(哈希聚合)

1、流聚合:

流聚合中又分两种:一种是不包含GROUP BY子句的也称为标量聚合,另外一种是包含GROUP BY子句聚合

标量聚合示例:

Group By聚合示例:

由执行计划可以看出,针对Group By字段上建立合适的索引,将省去额外的Sort操作。

2、哈希聚合:

 当数据量较大,且输入端数据无排序的情况下,查询优化器一般会使用哈希聚合(迭代器名称为:Hash Match)

 示例:

SELECT UnitPrice,COUNT(1) FROM Sales.SalesOrderDetail
GROUP BY UnitPrice

原文地址:https://www.cnblogs.com/Jabben_Yi/p/7398246.html