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

说说复合索引

写索引的博客太多了,一直不想动手写,有一下两个原因:
一是觉得有炒剩饭的嫌疑,有兄弟曾说:索引吗,只要在查询条件上建索引就行了,真的可以这么暴力吗?
二来觉得,索引是个非常大的话题,很难概括出所有的情况,你不整出点新意来,倒是有抄袭照搬的嫌疑

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

搭建测试环境:

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

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
begininsert 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

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

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

郑重的说明一点:

暂时不考虑聚集索引,毕竟一个表上只能有一个聚集索引,
别人也不是傻子,不会轻易去建聚集索引,聚集索引早被占用了
既然被占用了,我的原则是一般不去动别人现有的东西的,比如别人建了聚集索引,你给人家删了,根据自己的情况建聚集索引
这不是找骂么

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

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初步确定满足条件的数据,再进一步的进行过滤

  如果最开始就相对精确地确定了满足查询条件的数据范围,后面可以通过相对较小的代价来最终确认出满足条件的数据

  如果最开始相对模糊地却确定了满足查询条件的数据范围,那么这个过程的代价就相对比较大,虽然后面通过每一个条件的过,结果是一样的

  当然这种索引的建立跟数据分布有关,

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

  还是那句话:具体问题具体分析,避免经验主义,没有一刀切的手段可以解决所有的问题。

总结:

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

posted on 2016-06-24 09:24 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/5613097.html

SQL Server创建复合索引时,复合索引列顺序对查询的性能影响相关推荐

  1. SQL Server 创建表 添加主键 添加列常用SQL语句

    --删除主键 alter table 表名 drop constraint 主键名 --添加主键 alter table 表名 add constraint 主键名 primary key(字段名1, ...

  2. SQL Server 创建索引时的注意事项

    SQL code --创建索引时的注意事项 /***************************************************************************** ...

  3. SQL server 系统优化--通过执行计划优化索引(1) (转)

    SQL server 系统优化--通过执行计划优化索引(1) 前几天,远离上海,到了温州,在客户的这边处理系统慢,该系统每天正常down机7次左右,在线人员一多,系统运行缓慢,严重影响业务操作,到了无 ...

  4. 使用SQL编程创建100万条数据测试索引

    SQL编程创建100万条数据测试索引 CREATE TABLE `app_user`( `id` BIGINT (20) UNSIGNED NOT NULL AUTO_INCREMENT, `name ...

  5. SQL Server创建表语句介绍

    SQL Server创建表是最常见也是最常用的操作之一,下面就为您介绍SQL Server创建表的语句写法,供您参考,希望可以让您对SQL Server创建表方面有更深的认识. USE suntest ...

  6. SQL Server 2008还原数据库时出现“备份集中的数据库备份与现有的数据库不同”的解决方法

    SQL Server 2008还原数据库时出现"备份集中的数据库备份与现有的数据库不同"的解决方法 参考文章: (1)SQL Server 2008还原数据库时出现"备份 ...

  7. SQL Server 2008编写脚本时智能提示功能丢失的处理

    SQL Server 2008编写脚本时智能提示功能丢失的处理 1.查看工具选项中[启用IntelliSense]是否打开: 选择[工具]-->[选项]打开选项页面,依次展开[文本编辑器]--& ...

  8. SQL SERVER 创建GHUID命令:select newid();

    SQL SERVER 创建GHUID命令:select newid(); insert into persion2(id,name,age) values(newid(),'j',23); 插入有中文 ...

  9. SQL Server创建数据库和数据的增删改查

    SQL Server创建数据库和数据的增删改查 本文是针对数据的增删改查,数据的创建 首先我们使用命令创建sql server数据库 D盘新建一个文件夹DB use master go --创建数据库 ...

最新文章

  1. ROS-Baxter抓取
  2. ubuntu 16.04 python3 使用ryu
  3. linux下安装python dlib依赖
  4. spring mail 发送邮件
  5. 2008年夜饭时随手拍的两张照片
  6. 2016年个人技术总结(前端)
  7. 数据结构c语言版第四章题库,数据结构(C语言版)(第4版)习题
  8. Flutter布局锦囊---带彩条的文本字段
  9. 数据挖掘:模型状态评估
  10. Leetcode之字符串转换整数
  11. win10系统下Consul持久化
  12. 组态王如何让计算机关机,组态王软件系统登陆与退出.doc
  13. 阿根廷-10月摩托车行业实现正增长(+23.4%)
  14. ps懒人一键智能AI磨皮插件 去除皮肤瑕疵
  15. linux 快速建网站,如何快速建站,新手快速搭建网站教程
  16. 怎么把苹果手机通讯录导入华为手机_怎么恢复手机通讯录?最完整手机通讯录恢复方法大公开...
  17. 智能网联汽车激光雷达工作原理、性能比较与安全性分析
  18. Matlab中的傅里叶级数展开函数
  19. C语言中的指针,指针存在的意义
  20. 找个程序员做男朋友好难啊

热门文章

  1. 相分离在聚集多价信号蛋白过程中的作用Phase transitions in the assembly of multivalent signalling proteins
  2. 逻辑回归与梯度下降法
  3. lenovo电脑_办公笔记本电脑有哪些值得推荐?
  4. “21天好习惯”第一期-21
  5. mr InputFormat类
  6. Android图片控件,跟随列表(recyclerView)的上下滚动而同步平移。
  7. WebSocket协议:5分钟从入门到精通
  8. 【spring boot】5.spring boot 创建web项目并使用jsp作前台页面
  9. 在android 两个类之间 get,set方法传参使用
  10. POJ 1088 滑雪 (动规)