非汇集索引设计

        在SQL SERVER中,非汇集索引其实能够看做是一个含有汇集索引的表.但相比实际的表而言.非汇集索引中所存储的表的列数要窄不少,由于非汇集索引仅仅包含原表中非汇集索引的列和指向实际物理表的指针。数据库

    

    而且,对于非汇集索引表来讲,其中所存放的列是按照汇集索引来进行存放的.因此查找速度要快了不少。可是对于性能的榨取来讲,SQL SERVER老是竭尽所能,假如仅仅是经过索引就能够在B树的叶子节点获取所需数据,而再也不用经过叶子节点上的指针去查找实际的物理表,那性能的提高将会更胜一筹.并发

    下面咱们来看下实现这一点的几种方式.性能

 

非汇集索引的覆盖

    正如前面简介所说。非汇集索引其实能够看做一个汇集索引表.当这个非汇集索引中包含了查询所须要的全部信息时,则查询再也不须要去查询基本表,而仅仅是从非汇集索引就能获得数据:学习

   

   下面来看非汇集索引如何覆盖的:优化

   在adventureWorks的SalesOrderHeader表中,如今只有CustomerID列有非汇集索引,而BillToAddressID没有索引,咱们的查询计划会是这样:spa

   

   查询会根据CustomerID列上的非汇集索引找到相应的指针后,去基本表上查找数据.从执行计划能够想象,这个效率并不快。指针

   下面咱们来看覆盖索引,经过在CustomerID和BillToAddressID上创建非汇集索引,咱们覆盖到了上面查询语句的全部数据:索引

    

    经过覆盖索引,能够看到执行计划简单到不能再简单,直接从非汇集索引的叶子节点提取到数据,无需再查找基本表!开发

    这个性能的提高能够从IO统计看出来,下面咱们来看有覆盖索引和没有覆盖索引的IO对比:效率

    

    索引的覆盖不只仅带来的是效率的提高,还有并发的提高,由于减小了对基本表的依赖,因此提高了并发,从而减小了死锁!

   

 

理解INCLUDE的魔力

    上面的索引覆盖所带来的效率提高就像魔术同样,但别着急,正如我通篇强调的同样,everything has price.若是一个索引包含了太多的键的话,也会带来不少反作用。INCLUDE的做用使得非汇集索引中能够包含更多的列,但不做为“键”使用。

    好比:假设咱们上面的那个查询须要增长一列,则原来创建的索引没法进行覆盖,从而还须要查找基本表:

    

    可是若是要包含SubTotal这个总金额,则索引显得太宽,由于咱们的业务不多根据订单价格做为查询条件,则使用INCLUDE创建索引:

    

    理解INCLUDE包含的列和索引创建的列能够这样理解,把上述创建的含有INCLUDE的非汇集索引想像成:

     

     使用INCLUDE能够减小叶子“键”的大小!

 

非汇集索引的交叉

    非汇集索引的交叉看以看做是覆盖索引的扩展!

     因为不少缘由,好比:

  •     在生产环境中,咱们每每不能像上面创建覆盖索引那样随意改动现有索引,这可能致使的结果是你会更频繁的被客户打电话“关照”
  •     现有的非汇集索引已经很“宽”,你若是继续拓宽则增改查带来的性能降低的成本会高过提升查询带来的好处

     这时候,你能够经过额外创建索引。正如我前面提到的,非汇集索引的本质是表,经过额外创建表使得几个非汇集索引之间进行像表同样的Join,从而使非汇集索引之间能够进行Join来在不访问基本表的状况下给查询优化器提供所须要的数据:

    好比仍是上面的那个例子.咱们须要查取SalesOrderHeader表,经过BillToAddressID,CustomerID做为选择条件,能够经过创建两个索引进行覆盖,下面咱们来看执行计划:

   

   

   

非汇集索引的链接

     非汇集索引的链接其实是非汇集索引的交叉的一种特例。使得多个非汇集索引交叉后能够覆盖所要查询的数据,从而使得从减小查询基本表变成了彻底不用查询基本表:

     好比仍是上面那两个索引,这时我只查询非汇集索引中包含的数据,则彻底再也不须要查询基本表:

     

 

非汇集索引的过滤

    不少时候,咱们并不须要将基本表中索引列的全部数据所有索引,好比说含有NULL的值不但愿被索引,或者根据具体的业务场景,有一些数据咱们不想索引。这样能够:

  •     减小索引的大小
  •     索引减小了,从而使得对索引的查询获得了加速
  •     小索引对于增删改的维护性能会更高

    好比说,以下语句:

    

    咱们为其创建汇集索引后:

    

    这时咱们为其加上过滤条件,造成过滤索引:

    

    由上面咱们能够看出,使用过滤索引的场景要和具体的业务场景相关,对于为大量相同的查询条件创建过滤索引使得性能进一步提高

 

总结

    本文从介绍了SQL SERVER中非汇集索引的覆盖,链接,交叉和过滤。对于咱们每一点从SQL SERVER榨取的性能的提高每每会伴随着另外一方面的牺牲。做为数据库的开发人员或者管理人员来讲,以全面的知识来作好权衡将会是很是重要.系统的学习数据库的知识不但能大量减小逻辑读的数据,也能减小客户打电话"关照”的次数:-)

相关文章
相关标签/搜索