5 . 3 执 行 引 擎

时间:2023-01-14 17:14:44

5 . 3 执 行 引 擎
从本质上来说,执行引擎就是用于实现执行计划中物理操作符的,该过程中主要包含
数据访问、聚合、关联和并行等操作。
5 .3 .1 数 据 访 问 操 作
SQL Server可以使用表或者索引上的扫描以及查找操作来访问数据。扫描操作将针对

整个结构来进行,可能是一个堆表、一个聚集索引或者一个非聚集索引。查找操作是从索
引中查找所需的数据,因此不需要扫描整个结构。查找操作只发生在聚集索引和非聚集索
引上。如表5-1所示是数据访问操作的类型。

5 . 3 执 行 引 擎

1 . 扫描
下面来看看最简单的堆表扫描,这部分在第8章有详细演示,所以这里只进行简单演
示。打开执行计划并执行下面语句:
USE AdventureWorks2008R2 GO
SELECT *
FROM DatabaseLog
表扫描的执行计划如图5-6所示。
然后来看看最简单的聚集索引扫描。
USE AdventureWorks2008R2 GO
SELECT * FROM Person.Address
聚集索引扫描的执行计划如图5-7所示。

5 . 3 执 行 引 擎

聚集索引和表扫描都是通过扫描整个底层实体表来查找所需的数据。注意聚集索引本质
上也是表本身,只不过它是另外一种组织结构而已。同时,排序操作在扫描过程中是需要引
起注意的,当存在聚集索引时,表本身是有序的,这样可以避免一定程度的排序问题,如果
是堆表,排序操作将会导致严重的幵销。幸运的是,高级SQL Server版本提供了一种叫做 旋转式扫描的机制,该机制允许多个查询扫描相同的空间,避免每次都要单独排序。但是注
意不要因为有了改进就无视排序操作,这类操作往往是大开销操作,不适合大表处理。
对于非聚集索引扫描,也就是索引扫描,可以执行下面的语句:
SELECT AddressID, City, StateProvincelD FROM Person.Address索引扫描,即非聚集索引扫描的执行计划如图5-8所示

5 . 3 执 行 引 擎

这里提醒一下,如果想知道数据集是否有排序,可以看图5-8中的加框部分,如果它
为 True,证明数据已经排序。
2 . 查找
现在来看看索引查找,因为堆表上不存在查找操作,所以查找操作特指索引上的操作。
査找操作不需要扫描整个索引,它是通过B-tree结构来快速定位所需的数据的。下面两个 语句是用于聚集索引和非聚集索引查找操作的。
--聚集索引查找
SELECT AddressID, City, StateProvinceID FROM Person.Address WHERE AddressID = 12037
— 非聚集索引查找
SELECT AddressID, StateProvincelD FROM Person.Address WHERE StateProvincelD = 32
聚集索引及非聚集索引查找操作的执行计划如图5-9所示。

5 . 3 执 行 引 擎

 

 

3 . 书签查找
除了扫描和查找,还有一类叫书签(键)查找的数据访问操作,出现这类操作是因为一
个非聚集索引被优化器选为访问数据的索引,但是这个索引不能覆盖所有的列,这就导致
非聚集索引必须借助聚集索引键或者堆上的RID来定位其他数据。比如下面的语句:
SELECT AddressID, City, StateProvincelD, ModifiedDate FROM Person.Address WHERE StateProvincelD = 32
键查找(也叫Key Lookup,属于书签查找的一种)的执行计划如图5-10所示。

5 . 3 执 行 引 擎

现在看看键查找操作符的tooltips,如图5-11所示。

5 . 3 执 行 引 擎

可以得知,由于AddresdD不包含在非聚集索引中,而查询又需要用到它,所以需 要借助聚集索引来获取相关的数据(如果表上没有聚集索引,会出现R1D查找,即 R1D
Lookup, RID Lookup和 key Lookup统称为书签查找)。下面演示一下RID查找,首先需要
用到一个堆表,查询时用到了一个不能覆盖查询的非聚集索引,所以创建了一个非聚集索
引在堆表上,以便进行查询。
--创建非聚集索引
CREATE INDEX IX _ O b ject ON D atab aseL o g (O b je c t) - - R ID 查 找
SELECT * FROM D atabaseL og WHERE O b je c t = 'C i t y '
RID查找的执行计划如图5-12所示。
为了不影响后续演示,要在查看完效果
之后在计算机上删除刚才创建的非聚集索引。5 . 3 执 行 引 擎