将聚簇索引扫描优化为聚簇索引查找
Posted
技术标签:
【中文标题】将聚簇索引扫描优化为聚簇索引查找【英文标题】:Optimize the Clustered Index Scan into Clustered Index Seek 【发布时间】:2018-10-15 11:54:35 【问题描述】:有一个场景,我有 40 列的表,我必须选择一个表的所有数据(包括所有列)。我在表上创建了一个聚集索引,它包括聚集索引扫描,同时从表中获取完整的数据集。
我知道,如果没有任何过滤器或连接键,SQL Server 将选择 Clustered Index Scan 而不是 Clustered Index Seek。但是,我想通过将 Clustered Index Scan 优化为 Clustered Index Seek 来优化执行计划。有什么解决方案可以实现这一目标吗?请分享。
下面是执行计划的截图:
【问题讨论】:
为什么?它会像垃圾一样运行。 【参考方案1】:问题/请求中的某些内容不太正确,因为您所要求的内容将表现不佳。我怀疑这是因为误解了什么是聚集索引。
聚集索引——也许更好地表述为聚集表——是数据表,它不与表分离,它是表。如果表上数据的顺序已经基于 ITEM ID,那么扫描是查询的最有效访问方法(尤其是考虑到select *
)——你根本不想在这种情况下寻找——而且我由于排序运算符,请不要相信这是您的情况。
如果聚集表是基于另一个字段排序的,那么您将需要一个额外的非聚集索引来提供正确的顺序。然后,您将尝试强制执行一个非聚集索引扫描、嵌套循环到聚集索引查找的计划。这可以使用查询提示来实现,INNER LOOP JOIN
很可能会导致搜索 - 但也存在可以使用的 FORCESEEK
。
就性能而言,第二个选项永远不会赢 - 实际上你正在寻找一个临界点概念 (https://www.sqlskills.com/blogs/kimberly/the-tipping-point-query-answers/)
【讨论】:
【参考方案2】:好吧,我也想达到同样的效果,我希望在我的***查询上进行索引搜索而不是索引扫描。
SELECT TOP 5 id FROM mytable
这是查询的执行计划:
我什至尝试了Offset Fetch Next
的方法,计划是一样的。
为了避免索引扫描,我加入了一个假主键过滤器,如下所示:
SELECT TOP 5 id FROM mytable where id != 0
我知道,我的主键中不会有 0 值,所以我在顶部查询中添加了它,这被解析为索引查找而不是索引扫描:
尽管如此,查询计划比较给出了与其他类似的操作成本,对于这方面的索引查找和扫描。但我认为以这种方式实现索引搜索,这是db
执行的额外操作,因为它必须比较id是否为0。如果我们想要前几条记录,我们完全不需要它。
【讨论】:
以上是关于将聚簇索引扫描优化为聚簇索引查找的主要内容,如果未能解决你的问题,请参考以下文章