ORDER BY子句所用列是否可作为非聚集索引的INCLUDE列?
结论
你的场景下ORDER BY用到的LastUpdated列不适合作为非聚集索引的INCLUDE列,应当调整到非聚集索引的键列中。
原因说明
非聚集索引的核心规则如下:
- 索引键列会按定义的顺序参与索引排序,索引的B+树结构是严格按键列顺序组织的
- INCLUDE列仅存放在索引的叶子节点,不参与索引排序,在索引结构中是无序的
你当前的索引存在明显性能问题:
你的查询中Status、active都是等值过滤条件,现有索引里这两个字段之后的键列是Symbol,所以符合active=1、Status=999的索引行是按Symbol排序的,INCLUDE的LastUpdated完全无序。执行查询时需要先取出所有符合WHERE过滤规则的行,再对全部结果集做排序才能满足ORDER BY要求,当符合条件的行数较多时,排序操作会占用大量内存/CPU资源,甚至出现磁盘临时排序,性能损耗极大。
优化方案
将LastUpdated调整到键列的等值条件之后、过滤条件之前,调整后的索引如下:
CREATE NONCLUSTERED INDEX [IXNI__symboltab__Status_active_LastUpdated_Symbol] ON symboltab (Status,active,LastUpdated,Symbol) -- 键列已包含查询需要的所有字段,无需额外INCLUDE列
调整后的收益:
符合active=1、Status=999的索引行会严格按照LastUpdated ASC的顺序组织,查询时仅需从索引头部开始扫描,逐行判断Symbol是否符合过滤规则,取够10000条符合条件的数据就可以直接终止查询,完全不需要额外排序操作,性能会有数量级的提升。
补充说明:仅当你的查询中ORDER BY对应的列筛选后结果集非常小(比如只有几十、几百行),排序开销可以忽略时,才可以考虑将ORDER BY列放在INCLUDE中,你的场景要取TOP 10000行,显然不符合这个前提。
内容的提问来源于stack exchange,提问作者Himani
相关产品推荐
相关产品推荐

