zoukankan      html  css  js  c++  java
  • 查询优化器内核剖析第七篇:执行引擎之数据访问操作Scan

     

     查询优化器内核剖析第七篇:执行引擎之数据访问操作---Scan

    从本篇了开始的接下来的几篇文章将会介绍与执行引擎相关的知识。

         

     

      系列文章索引:       

     

           执行引擎就是由大量的物理操作组成的(而这些物理操作又会去调用存储引起的相关方法),这些操作被查询处理器用来高效的执行我们的查询。

    这里不要将查询处理器与查询优化器搞混淆,它们不是同一个东西。为了使得大家对相关的概念有一个清楚的认识,请看到下面这一个图:

     

    20120327204524.png

     

    从图中,就可以一目了然的直到查询处理器与查询优化器之间的关系:

      1. 数据库基本上有两大部分组成:关系引擎,存储引擎。(建议朋友们去仔细的阅读这几篇文章:SQL 内部机制之:一个查询的生命周期
      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

     

          还是和之前一样,我们从一个例子入手,这里依然使用示例数据库AdventureWorks。我们首先来看到一个Table Scan的操作(也就是整表扫描) ,看到如下的查询:

     

    20120327204624.png

     

    查看实际的执行计划,如下图:

     

    20120327204649.png

     

    通过查看DatabaseLog表的定义,我们发现这个表是一个堆表,即,这个表没有聚集索引,如下所示:

     20120327204716.png

    下面,我们再看一个Clustered Index Scan(聚集索引扫描)的例子,看到如下查询:

     

    20120327204757.png

     

    执行计划如下如所示:

     

    20120327204830.png

     

            通过查看Address表的定义,发现这个表确实还有聚集索引:

     

    20120327204900.png

     

            可以上面的例子可以知道:

      1. 虽然同是进行了 Scan操作,但是因为表的一些特性不同,而最后选择的具体的物理操作Scan也不一样。
      2. 不管是Table Scan还是Clustered Index Scan,它们都是对相应的数据结构进行了全部的扫描,不同的是:前者发生在堆表上,后者发生在含有聚集索引的表上。

    下面,给大家看一个比较有意思的查询:

     

    20120327205159.png

    执行计划如下:

     

    20120327205446.png

     

            图中显示的是Index  Scan,也就说,这个查询没有去扫描表的所有数据页,而是去扫描索引,这个成本小得多。之所以进行了这个操作,是因为在这个表上存在一个非聚集索引,定义如下:

     

    20120327205509.png

     

            这个非聚集索引包含了我们查询中的两个字段:[City],[StateProvinceID]。又因为AddressID是这个表的聚集索引,对于一个有聚集索引的表而言,它的所有的非聚集索引都会包含一个对聚集索引的引用,这样是为了加快数据检索的速度(大家可以想想为什么?)。所以,我们上面查询中的三个操作都可以在索引页中找到,就没有必要去扫描底层的表了。

     

  • 相关阅读:
    shell 去除utf8文件中bom头的方法
    bad interpreter:No such file or directory
    桥接配置虚拟机网络
    coreseek因为重启遇到的问题
    监听微信内置浏览器 返回点击事件
    phpredis 扩展装完后,重启php不生效的原因之一
    linux上ThinkPHP中原本正常的css,js文件找不到的解决方式
    vps
    java基础-《JAVA语言程序设计与数据结构》笔记
    面经问题总结——django相关
  • 原文地址:https://www.cnblogs.com/yanyangtian/p/2420611.html
Copyright © 2011-2022 走看看