查询优化器内核剖析第七篇:执行引擎之数据访问操作---Scan
2013-02-28 17:32
411 查看
从本篇了开始的接下来的几篇文章将会介绍与执行引擎相关的知识。
执行引擎就是由大量的物理操作组成的(而这些物理操作又会去调用存储引起的相关方法),这些操作被查询处理器用来高效的执行我们的查询。
这里不要将查询处理器与查询优化器搞混淆,它们不是同一个东西。为了使得大家对相关的概念有一个清楚的认识,请看到下面这一个图:
20120813083152.png(19.21
K)
8/13/2012 8:48:36 AM
从图中,就可以一目了然的直到查询处理器与查询优化器之间的关系:
1.数据库基本上有两大部分组成:关系引擎,存储引擎。
2.我们这里所说的“查询处理器”就是图中的关系引擎,而查询优化器只是其中的一个部分。
我们最近将要介绍的“执行引擎”,就是上图中的“Query Executor”。在介绍执行引擎的过程中,我这里主要会着重的介绍几类在我们查询中常见的一些操作:数据访问,聚合,Join,还有并行操作。当然,在执行引擎中,还有更多的操作,如果大家感兴趣,可以去参看SQL
Server的联机丛书。
我们首先将会介绍给数据访问的几个操作:scan,seek,还有lookup。
相信大家对这些操作应该有所了解的,我这里稍微的提及一下:
Scan:这个操作会读取整个数据结构,这个数据结构可以是一个堆表,聚集索引,非聚集索引。
Seek:这个操作不会读取整个数据结构,而是直接通过索引定位到要读取的那一行。所以Seek操作只能发生在聚集索引与非聚集索引上。
堆表:就是没有建立聚集索引的表,表中的数据没有按照顺序进行存储。一旦一个表建立了聚集索引,那么表中的数据就会按照聚集索引排序存储。
另外,非聚集索引可以建立在堆表上,也可以建立在还有聚集索引的表上。
我们通过下面的一个表做一下总结(看看不同的数据结构可以支持何种物理操作),然后迅速进入Scan操作的详细讲解。
还是和之前一样,我们从一个例子入手,这里依然使用示例数据库AdventureWorks。我们首先来看到一个Table
Scan的操作(也就是整表扫描)
,看到如下的查询:
20120813083257.png(5.74
K)
8/13/2012 8:48:36 AM
查看实际的执行计划,如下图:
20120813083329.png(13.23
K)
8/13/2012 8:48:36 AM
通过查看DatabaseLog表的定义,我们发现这个表是一个堆表,即,这个表没有聚集索引,如下所示:
20120813083826.png(14.92
K)
8/13/2012 8:48:36 AM
下面,我们再看一个Clustered Index Scan(聚集索引扫描)的例子,看到如下查询:
20120813083930.png(7.63
K)
8/13/2012 8:48:36 AM
执行计划如下如所示:
20120813084439.png(17.53
K)
8/13/2012 8:48:36 AM
通过查看Address表的定义,发现这个表确实还有聚集索引:
20120813084522.png(17.95
K)
8/13/2012 8:48:36 AM
可以上面的例子可以知道:
1.虽然同是进行了
Scan操作,但是因为表的一些特性不同,而最后选择的具体的物理操作Scan也不一样。
2.不管是Table Scan还是Clustered
Index Scan,它们都是对相应的数据结构进行了全部的扫描,不同的是:前者发生在堆表上,后者发生在含有聚集索引的表上。
下面,给大家看一个比较有意思的查询:
20120813084806.png(13.45
K)
8/13/2012 8:48:36 AM
执行计划如下:
20120813084849.png(17.86
K)
8/13/2012 8:48:36 AM
图中显示的是Index Scan,也就说,这个查询没有去扫描表的所有数据页,而是去扫描索引,这个成本小得多。之所以进行了这个操作,是因为在这个表上存在一个非聚集索引,定义如下:
20120813084925.png(17.20
K)
8/13/2012 8:48:36 AM
这个非聚集索引包含了我们查询中的两个字段:[City],[StateProvinceID]。又因为AddressID是这个表的聚集索引,对于一个有聚集索引的表而言,它的所有的非聚集索引都会包含一个对聚集索引的引用,这样是为了加快数据检索的速度(大家可以想想为什么?)。所以,我们上面查询中的三个操作都可以在索引页中找到,就没有必要去扫描底层的表了。
执行引擎就是由大量的物理操作组成的(而这些物理操作又会去调用存储引起的相关方法),这些操作被查询处理器用来高效的执行我们的查询。
这里不要将查询处理器与查询优化器搞混淆,它们不是同一个东西。为了使得大家对相关的概念有一个清楚的认识,请看到下面这一个图:
20120813083152.png(19.21
K)
8/13/2012 8:48:36 AM
从图中,就可以一目了然的直到查询处理器与查询优化器之间的关系:
1.数据库基本上有两大部分组成:关系引擎,存储引擎。
2.我们这里所说的“查询处理器”就是图中的关系引擎,而查询优化器只是其中的一个部分。
我们最近将要介绍的“执行引擎”,就是上图中的“Query Executor”。在介绍执行引擎的过程中,我这里主要会着重的介绍几类在我们查询中常见的一些操作:数据访问,聚合,Join,还有并行操作。当然,在执行引擎中,还有更多的操作,如果大家感兴趣,可以去参看SQL
Server的联机丛书。
我们首先将会介绍给数据访问的几个操作:scan,seek,还有lookup。
相信大家对这些操作应该有所了解的,我这里稍微的提及一下:
Scan:这个操作会读取整个数据结构,这个数据结构可以是一个堆表,聚集索引,非聚集索引。
Seek:这个操作不会读取整个数据结构,而是直接通过索引定位到要读取的那一行。所以Seek操作只能发生在聚集索引与非聚集索引上。
堆表:就是没有建立聚集索引的表,表中的数据没有按照顺序进行存储。一旦一个表建立了聚集索引,那么表中的数据就会按照聚集索引排序存储。
另外,非聚集索引可以建立在堆表上,也可以建立在还有聚集索引的表上。
我们通过下面的一个表做一下总结(看看不同的数据结构可以支持何种物理操作),然后迅速进入Scan操作的详细讲解。
数据结构 | Scan | Seek |
堆表 | Table Scan | |
聚集索引 | Clustered Index Scan | Clustered Index Seek |
非聚集索引 | Index Scan | Index Seek |
Scan的操作(也就是整表扫描)
,看到如下的查询:
20120813083257.png(5.74
K)
8/13/2012 8:48:36 AM
查看实际的执行计划,如下图:
20120813083329.png(13.23
K)
8/13/2012 8:48:36 AM
通过查看DatabaseLog表的定义,我们发现这个表是一个堆表,即,这个表没有聚集索引,如下所示:
20120813083826.png(14.92
K)
8/13/2012 8:48:36 AM
下面,我们再看一个Clustered Index Scan(聚集索引扫描)的例子,看到如下查询:
20120813083930.png(7.63
K)
8/13/2012 8:48:36 AM
执行计划如下如所示:
20120813084439.png(17.53
K)
8/13/2012 8:48:36 AM
通过查看Address表的定义,发现这个表确实还有聚集索引:
20120813084522.png(17.95
K)
8/13/2012 8:48:36 AM
可以上面的例子可以知道:
1.虽然同是进行了
Scan操作,但是因为表的一些特性不同,而最后选择的具体的物理操作Scan也不一样。
2.不管是Table Scan还是Clustered
Index Scan,它们都是对相应的数据结构进行了全部的扫描,不同的是:前者发生在堆表上,后者发生在含有聚集索引的表上。
下面,给大家看一个比较有意思的查询:
20120813084806.png(13.45
K)
8/13/2012 8:48:36 AM
执行计划如下:
20120813084849.png(17.86
K)
8/13/2012 8:48:36 AM
图中显示的是Index Scan,也就说,这个查询没有去扫描表的所有数据页,而是去扫描索引,这个成本小得多。之所以进行了这个操作,是因为在这个表上存在一个非聚集索引,定义如下:
20120813084925.png(17.20
K)
8/13/2012 8:48:36 AM
这个非聚集索引包含了我们查询中的两个字段:[City],[StateProvinceID]。又因为AddressID是这个表的聚集索引,对于一个有聚集索引的表而言,它的所有的非聚集索引都会包含一个对聚集索引的引用,这样是为了加快数据检索的速度(大家可以想想为什么?)。所以,我们上面查询中的三个操作都可以在索引页中找到,就没有必要去扫描底层的表了。
相关文章推荐
- 查询优化器内核剖析第七篇:执行引擎之数据访问操作---Scan
- 查询优化器内核剖析第八篇:执行引擎之数据访问操作---Seek与Lookup
- 查询优化器内核剖析第九篇:执行引擎之数据访问操作---Bookmark Lookup
- 查询优化器内核剖析第十篇:执行引擎之数据访问操作- Aggregations(聚合)
- 查询优化器内核剖析第八篇:执行引擎之数据访问操作
- 查询优化器内核剖析第八篇:执行引擎之数据访问操作---Seek(上)
- 查询优化器内核剖析第四篇:从一个实例看执行计划
- 查询优化器内核剖析第三篇:查询的执行与计划的缓存 & Hint提示
- 查询优化器内核剖析第五篇:进一步的了解执行计划
- 查询优化器内核剖析第二篇:产生候选执行计划&执行计划成本估算
- 查询优化器内核剖析第三篇:查询的执行与计划的缓存 & Hint提示
- 查询优化器内核剖析第二篇:产生候选执行计划&执行计划成本估算
- 【PHP7内核剖析】3.3 Zend引擎执行过程
- Beginning Spring学习笔记——第4章(二)使用Spring执行数据访问操作
- RX操作符之对Observable发射的数据执行变换操作二(scan、groupby、buffer、window)
- 查询优化器内核剖析第三篇:查询的执行与计划的缓存 & Hint提示
- .net中利用oracle产品自带的数据访问组件(Oracle.DataAccess.dll)提升批量更新操作的执行效率
- 查询优化器内核剖析第四篇:从一个实例看执行计划
- .net中利用oracle产品自带的数据访问组件(Oracle.DataAccess.dll)提升批量更新操作的执行效率
- 查询优化器内核剖析第五篇:进一步的了解执行计划