我有以下表格架构 -
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列没有任何索引,为什么它正在访问聚簇索引?
我相信,这种情况正在发生,因为聚集索引驻留在数据页面上。
有人能告诉我我的假设是否正确吗?或者还有其他原因吗?
答案 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,那么您将进行无序分配扫描。