非聚集索引的覆盖
非聚集索引其实可以看作一个聚集索引表,当这个非聚集索引中包含了查询所需要的所有信息时,则查询不再需要去查询基本表,而仅仅是从非聚集索引就能得到数据
测试1:SalesOrderHeader表中,现在只有CustomerID列有非聚集索引,而BillToAddressID没有索引,我们的查询计划会是这样
总结:查询会根据CustomerID列上的非聚集索引找到相应的指针后,去基本表上查找数据,从执行计划可以想象,这个效率并不快。
测试2:通过在CustomerID和BillToAddressID上建立非聚集索引,我们覆盖到了上面查询语句的所有数据:
总结:通过覆盖索引,可以看到执行计划简单到不能再简单,直接从非聚集索引的叶子节点提取到数据,无需再查找基本表
IO统计:
上面是测试1,下面是测试2
总结: 索引的覆盖不仅仅带来的是效率的提升,还有并发的提升,因为减少了对基本表的依赖,所以提升了并发,从而减少了死锁!
INCLUDE的魔力
如果一个索引包含了太多的键的话,也会带来很多副作用。INCLUDE的作用使得非聚集索引中可以包含更多的列,但不作为“键”使用
测试3: 假设我们上面的那个查询需要增加一列,则原来建立的索引无法进行覆盖,从而还需要查找基本表
因为我们的业务很少根据订单价格作为查询条件,则使用INCLUDE建立索引
非聚集索引的交叉
交叉看以看作是覆盖索引的扩展
假如现有的非聚集索引已经很“宽”,你如果继续拓宽则增改查带来的性能下降的成本会高过提高查询带来的好处
这时候,可以通过额外建立索引。非聚集索引的本质是表,通过额外建立表使得几个非聚集索引之间进行像表一样的Join
非聚集索引的连接
非聚集索引的连接实际上是非聚集索引的交叉的一种特例(交叉是查询所有数据,而连接是只查询包含索引健的数据)
非聚集索引的过滤
很多时候,我们并不需要将基本表中索引列的所有数据全部索引,比如说含有NULL的值不希望被索引,或者根据具体的业务场景,有一些数据我们不想索引(创建索引时添加WHERE过滤)