SQL Server建立复合索引时,复合索引列顺序对查询的性能影响

原文: SQL Server建立复合索引时,复合索引列顺序对查询的性能影响

 

 说说复合索引html

写索引的博客太多了,一直不想动手写,有一下两个缘由:
一是以为有炒剩饭的嫌疑,有兄弟曾说:索引吗,只要在查询条件上建索引就好了,真的能够这么暴力吗?
二来以为,索引是个很是大的话题,很难归纳出全部的状况,你不整出点新意来,却是有抄袭照搬的嫌疑性能

既然写了,就写一点稍微不同的东西出来,
好了,废话打住,开搞测试

 

搭建测试环境:spa

建立一张表,模拟实际业务中的一个表,往里面填入数据,
时间字段上,相对按照时间均匀地填充,其余字段以GUID填充code

Create table BusinessInfoTable
(
    BuniessCode1 varchar(50),
    BuniessCode2 varchar(50),
    BuniessCode3 varchar(50),
    BuniessCode4 varchar(50),
    BuniessStatus1 tinyint,
    BuniessStatus2 tinyint,
    BuniessDateTime1 Datetime,
    BuniessDateTime2 Datetime,
    OtherColumn1 varchar(50),
    OtherColumn2 varchar(50),
    OtherColumn3 varchar(50)
)



declare @i int=0
while @i<1000000
begin
    insert into BusinessInfoTable 
    values 
    (
        NEWID(),NEWID(),NEWID(),NEWID(),RAND()*100,RAND()*100,
        DATEADD(MI,@i,GETDATE()),DATEADD(MI,@i,GETDATE()),NEWID(),NEWID(),NEWID()
    )
    set @i=@i+1
end

如今有这么一个查询(实际上查询远比这个复杂,我简化一点,不要说我刻意造环境)htm

    select OtherColumn2,
           BuniessStatus1,
           BuniessStatus2,
           BuniessDateTime1,
           BuniessDateTime2
    from BusinessInfoTable 
    where  BuniessDateTime1 between '2016-6-21' and '2016-6-28'
        and BuniessDateTime2 between '2016-6-21' and '2016-6-28'
        and BuniessStatus1    =    55
        and BuniessStatus2    =    66

郑重的说明一点:blog

暂时不考虑汇集索引,毕竟一个表上只能有一个汇集索引,
别人也不是傻子,不会轻易去建汇集索引,汇集索引早被占用了
既然被占用了,个人原则是通常不去动别人现有的东西的,好比别人建了汇集索引,你给人家删了,根据本身的状况建汇集索引
这不是找骂么索引


有经验的你必定考虑符合索引了,同时考虑到为避免Key Lookup致使的书签查找,咱们把查询索要的OtherColumn2列include进来
好比这样get

CREATE NONCLUSTERED INDEX IDX_1 ON BusinessInfoTable 
(BuniessStatus1,BuniessStatus2,BuniessDateTime1,BuniessDateTime2)
INCLUDE(OtherColumn2)

 

或者这样,只是索引列顺序不同博客

CREATE NONCLUSTERED INDEX IDX_1 ON BusinessInfoTable
(BuniessDateTime1,BuniessDateTime2,BuniessStatus1,BuniessStatus2)
INCLUDE(OtherColumn2)

 

固然能够随意调整四个列的顺序,我就不过多地作演示了,有兴趣的本身试

这里的前导列的顺序并不会影响到索引的使用,查询的时候都是非汇集索引Seek,绝对的

那么问题来了,彻底同样的查询条件,结果同样,使用不一样的索引,索引的区别仅仅是列顺序不同,其代价同样吗,先猜想一下,有区别吗?

 

 

  一样查询,使用不一样索引的结果(分别是上面的IDX_1和IDX_2):

下面看图说话

看看IO状况

 

缘由分析

  看来是有点差异吧,好彷佛这个差异还真不小(以往写文章,我测试环境弄很差,对比出来的效果不明显,感受没啥说服力,此次对比仍是比较明显的)

  究竟缘由在何?

  索引是以平衡树(B树)的方式存在的,复合索引的列的顺序决定了B树的信息的存储的顺序

  若是是以BuniessStatus1列为前导列,由于BuniessStatus1分布的范围(相对)较小,

  这样在查询的时候经过BuniessStatus1=55就能够过滤出来一个比较小的结果集,后面依次用其余条件过滤就相对较快了

  好比BuniessStatus1=55过滤出来符合条件的数据有5条,

  加上BuniessStatus2 BuniessDateTime1 BuniessDateTime2 这三个条件再过滤,出来一条数据。

 

  若是BuniessDateTime1 是索引的前导列,用BuniessDateTime1 between '2016-6-21' and '2016-6-28'过滤

  可能会有10000条数据,而后依次再用 BuniessDateTime2,BuniessStatus1, BuniessStatus2过滤

  最后也只有一条符合条件的数据。

   差异就在于:一开始的过滤条件,决定了查询多少page初步肯定知足条件的数据,再进一步的进行过滤

  若是最开始就相对精确地肯定了知足查询条件的数据范围,后面能够经过相对较小的代价来最终确认出知足条件的数据

  若是最开始相对模糊地却肯定了知足查询条件的数据范围,那么这个过程的代价就相对比较大,虽而后面经过每个条件的过,结果是同样的

 

  固然这种索引的创建跟数据分布有关,

  可是,我没有下结论说,复合索引必定要按照什么什么顺序来是最好的

  仍是那句话:具体问题具体分析,避免经验主义,没有一刀切的手段能够解决全部的问题。

 

总结:

  本文经过一个简单的例子,分析了建立符合索引时,列的顺序对查询的影响,说明在建立索引的时候,不只仅要考虑在哪些列上建立索引,同时也要注意到,索引列的顺序,是否会对查询产生影响。避免一说到索引,就是“在查询条件上建索引”的暴力作法。

相关文章
相关标签/搜索