我正在尝试了解覆盖索引。在 Northwind 数据库中,我从表Categories中选择:
如您所见,该表在CategoryName列上有一个非聚集索引。
此 SQL 查询:
select CategoryName from Categories where Categories.CategoryName like 'Beverages'
返回带有索引查找的执行计划:
然而,这:
select CategoryName ,Description from Categories where Categories.CategoryName like 'Beverages'
通过使用主键索引的索引扫描返回此执行计划,这不是预期的:
只有当我强制使用非聚集索引进行查询时,我才能找到预期的行为:
select CategoryName ,Description from Categories
with(index(CategoryName))
where Categories.CategoryName like 'Beverages'
问题是什么?
您的索引中没有
Description
列,但您的查询中有列。因此,SQL Server 必须获取此列。有两种选择:如果您的统计数据让 SQL Server 认为它会读取大量数据,则 SQL Server 会在非聚集索引查找 + 键查找或聚集索引扫描之间做出选择,这称为临界点。
因为,如果 SQL Server 必须读取大量数据,聚集索引扫描可以比非聚集索引查找 + 键查找更有效。
这里有一篇很好的博客文章。
这是因为非聚集索引不包括
Description
所以它不包括第二个查询。那么仅有的两个选项是使用该非聚集索引,然后对主键(在这种情况下实际上是聚集索引)进行键查找以获取该字段(两个操作),或者从一开始就使用聚集索引来查找和过滤数据,因为聚集索引包括所有字段(一次操作)。
Description
它根据执行计划中操作员成本的差异来选择一个操作而不是另一个操作,这将因查询和数据集的不同而不同,具体取决于数据的基数等。
这被称为引爆点。
如果您更改了非聚集索引以包含该
Description
字段,那么它应该在一个操作中使用非聚集索引(甚至不需要键查找)。例如: