SQL Server:为什么聚集索引扫描而不是表扫描?

时间:2012-09-27 06:21:58

标签: sql sql-server

我有以下表格架构 -

CREATE TABLE [dbo].[TEST_TABLE]
(
    [TEST_TABLE_ID] [int] IDENTITY(1,1) NOT NULL,
    [NAME] [varchar](40) NULL,
    CONSTRAINT [PK_TEST_TABLE] PRIMARY KEY CLUSTERED 
    (
        [TEST_TABLE_ID] ASC
    )
)

我在TEST_TABLE中插入了大量数据。

由于我已将TEST_TABLE_ID列标记为主键,因此将在TEST_TABLE_ID上创建聚集索引。

当我运行以下查询时,执行计划显示Clustered Index Scan,这是预期的。

SELECT * FROM TEST_TABLE WHERE TEST_TABLE_ID = 34

但是,当我运行以下查询时,我期待Table Scan为NAME列没有任何索引:

SELECT * FROM TEST_TABLE WHERE NAME LIKE 'a%'

但在执行计划中,它显示Clustered Index Scan

由于NAME列没有任何索引,为什么它正在访问聚簇索引?

我相信,这种情况正在发生,因为聚集索引驻留在数据页面上。

有人能告诉我我的假设是否正确吗?或者还有其他原因吗?

5 个答案:

答案 0 :(得分:3)

聚簇索引是存储所有表数据的索引。因此,表扫描与聚簇索引扫描相同。

在没有聚簇索引(“堆”)的表中,表扫描需要遍历所有数据页。这就是查询优化器所谓的“表扫描”。

答案 1 :(得分:3)

正如其他人所解释的,对于具有聚集索引的表,聚簇索引扫描表示表扫描

换句话说,该表是聚集索引。

你的错误是你的第一个查询执行计划:

SELECT * 
FROM TEST_TABLE 
WHERE TEST_TABLE_ID = 34 ;

它执行 Clustered Index Seek 而不是扫描。它不必搜索(扫描)整个表(聚集索引),它直接到达点(搜索)并检查是否有一行{{1存在。

您可以在 SQL-Fiddle 中看到一个简单的测试,以及两个执行计划的不同之处。

答案 2 :(得分:2)

该表以存储为聚簇索引。扫描表的唯一方法是扫描聚簇索引。只有没有聚簇索引的表本身才能有“表扫描”。

答案 3 :(得分:1)

这是因为该表具有聚簇索引,它将扫描整个聚簇索引以返回基于where子句的所有行。你应该怎么看到丢失的索引消息。

答案 4 :(得分:0)

当您在表上构建聚簇索引时,SQL Server会根据聚集索引键(在您的情况下为Test_Table_ID)逻辑地对该表的行进行排序。

但是,当您看到Clustered Index Scan运算符时,这可能会产生一些误导。如果满足某些条件(等同于SQL Server不关心数据的顺序),则SQL Server仍然能够执行无序分配扫描,这与表扫描比聚簇索引扫描更相似,因为它实际上,基于IAM链,按照分配顺序读取CI的叶级(表数据页),而不是跟随索引中的指针。这可能会提高性能,因为碎片(页面超出物理顺序)不会降低性能

要查看是否发生这种情况,请查看执行计划中的Ordered属性。如果将其设置为False,那么您将进行无序分配扫描。