我知道,当我们使用覆盖索引时,sql server在执行计划中仅使用索引搜索(非聚簇)或索引扫描(非聚集)运算符,而不通过查找运算符检索数据。但为什么不在聚簇索引中查找值呢?非聚簇索引不会在叶级别上存储数据,因此无论它包含多少列,它都必须要求聚簇索引返回数据行,因此它应该是执行计划中的查找运算符。我对吗?我读过https://www.red-gate.com/simple-talk/sql/learn-sql-server/using-covering-indexes-to-improve-query-performance/和其他文章,但没有解释。
答案 0 :(得分:2)
所有级别的任何索引都存储定义该索引键的列的值。此外,在非聚集索引的叶级别,叶子存储任何其他列的值,这些列是聚簇索引键 1 的一部分,并且不是非聚类索引键的一部分聚簇索引键,因为这是执行聚簇索引查找的方式。
如果查询需要检索的唯一列是非聚集索引键的一部分或者是聚簇索引键的一部分,那么我们已经通过导航获得了所有这些列值。非聚集索引。
通常,查询不会尝试检索行,只检索特定列中的行值。
作为类比,请考虑您正在为整个城镇进行人口普查,并存储所有数据和实体卡。这些卡包含人的姓名,地址,出生日期,当前职业等。进一步假设每个人都有一个唯一的地址,因此您决定按照地址顺序将所有这些卡存储在一个大的盒子文件中。这是您的聚集索引。
您经常希望根据姓名找到人。因此,您创建另一组索引卡,告诉您,对于姓氏和名字的任何特定组合,具有该名称的人所在的所有地址。您将这些卡放在第二个盒子文件中,并按姓氏,名字值对它们进行排序。这是你的非clusered索引。
最后,假设您的任务是确定所有姓氏为Radish
的人居住的街道。显然,您可以使用非聚集索引来识别姓氏为Radish
的所有人。但请记住,此二级索引中的卡片会为您提供这些人的地址。如果我们唯一的任务是确定他们的街道,我们已经掌握了这些信息。我们无需查看所有原始人口普查卡,其中包含我们已经未要求的各种信息,只是为了完成此查询。
1 自2012年以来,在INCLUDE
子句中为索引定义确定了任何其他列。
答案 1 :(得分:0)
由于覆盖索引包含查询的所有SELECT项,因此无需转到表数据并尝试从数据文件中读取。您尝试阅读的数据已包含在覆盖索引中。
因此,您可以通过索引扫描读取所有覆盖索引,也可以使用索引搜索直接读取。