【问题标题】:Why the differences in execution plan between nonclustered and clustered index in SQL Server?为什么 SQL Server 中非聚集索引和聚集索引的执行计划存在差异?
【发布时间】: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


【解决方案1】:

聚集索引定义了数据在表中物理存储的顺序,但非聚集索引不对表内的物理数据进行排序。事实上,非聚集索引存储在一个位置和表中数据存储在另一个地方。

如果你使用Non-Clustered Index,当你调用它的属性时它会在Index seek (NonClustered)模式下工作,但是如果你把where放在Non-Clustered Index模式但调用select更多不是覆盖索引更改模式的表达式给Table scan

包含列的索引在覆盖查询时提供了最大的好处。这意味着索引包括查询引用的所有列,因为您可以添加数据类型、数量或大小不允许作为索引键列的列

但在Clustered Index 中,由于实际排序是由它完成的,所以你在Clustered index seek (clustered) 模式下都进行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-22
    • 2018-05-08
    • 2016-09-05
    • 1970-01-01
    • 2014-04-27
    • 2011-10-07
    • 2012-10-01
    相关资源
    最近更新 更多