【发布时间】:2020-04-15 06:44:58
【问题描述】:
请解释为什么非聚集索引和聚集索引之间存在以下差异。 首先,我运行以下两个 select 语句。
select *
from [dbo].[index_test2]
where id = 1 -- Nonclustered index on id column
select *
from [dbo].[index_test1]
where id = 1 -- Clustered index on id column
执行计划显示第一个查询的“表扫描”和第二个查询的“集群索引查找(集群)”。
然后我运行下面两个语句。
select id
from [dbo].[index_test2]
where id = 1 -- Nonclustered index on id column
select id
from [dbo].[index_test1]
where id = 1 -- Clustered index on id column
执行计划显示第一个查询为“索引查找(非集群)”,第二个查询为“集群索引查找(集群)”。
从以上两种情况可以看出,当使用聚集索引时,它会进行“索引搜索”,但对于非聚集索引,它会显示“表扫描”(使用 * 执行)并显示“索引搜索(非聚集索引)” )"(使用索引应用列 ID 执行)。
谁能解释一下为什么 NonClustered 索引对这两种情况的反应不同?
【问题讨论】:
-
首先要记住的是聚集索引就是你的表。表上只能有一个聚集索引,因为它实际上是具有索引键顺序的行的表。在您的第一个测试用例中,
select *未被非聚集索引覆盖,索引仅包含id列,因此需要进行表扫描才能返回所有列。在您的第二个测试用例中,select id被非聚集索引覆盖,因此它可以直接从索引返回行,而不是执行表扫描。 -
如果您执行
SELECT *,典型的非聚集索引将无法“覆盖”查询,例如提供需要从查询返回的所有列。如果 SQL Server 使用非聚集索引来查找值id = 1,则它必须执行(相当昂贵的)Key lookup 以从实际数据页中获取其他数据。对整个表执行此操作太昂贵了 - 仅扫描整个表“更便宜”。这就是您不应该在任何地方都使用SELECT *的主要原因之一 - 尝试仅选择那些真正需要的列 -
@ThangarajJ 。 . .你的桌子有多大?在非常小的表上,全表扫描是合理的。
标签: sql sql-server ssms