表扫描和聚簇索引扫描有什么区别?


63

由于Table ScanClustered Index Scan本质上都扫描了表中的所有记录,为什么聚集索引扫描应该更好?

为例 - 什么时候有许多记录?:

declare @temp table(
    SomeColumn varchar(50) 
) 

insert into @temp 
select 'SomeVal' 

select * from @temp 

----------------------------- 

declare @temp table(
    RowID int not null identity(1,1) primary key, 
    SomeColumn varchar(50) 
) 

insert into @temp 
select 'SomeVal' 

select * from @temp 
70

在没有聚簇索引(堆表)的表中,数据页没有链接在一起 - 因此遍历页需要lookup into the Index Allocation Map

然而,一个簇表有data pages linked in a doubly linked list - 使顺序扫描速度更快一些。当然,作为交换,您在处理在INSERT,UPDATEDELETE上保持数据页顺序的开销。但是,堆表需要第二次写入IAM。

如果查询有RANGE运营商(例如:SELECT * FROM TABLE WHERE Id BETWEEN 1 AND 100),然后聚集表(在保证的顺序是)会更有效率 - 因为它可以使用索引页找到相关的数据页(S)。堆将不得不扫描所有行,因为它不能依赖于排序。

而且,当然,聚集索引可以让您执行CLUSTERED INDEX SEEK,这对于性能而言非常理想......没有索引的堆总是会导致表扫描。

所以:

  • 对于您选择的所有行的示例查询中,唯一的区别是双向链表聚集索引维护。这应该使您的聚簇表比一个具有大量行的堆快一点点。

  • 对于含有WHERE子句的查询,可以(至少部分)通过聚集索引满足您的要求,因为排序 - 您将不必扫描整个表。

  • 对于不满足聚簇索引的查询,你几乎...甚至...再次,唯一的区别是顺序扫描的双向链表。无论如何,你都不是最理想的。

  • 对于INSERT,UPDATEDELETE堆可能赢或不赢。堆不必维持顺序,但需要再次写入IAM。我认为相对的性能差异可以忽略不计,但也依赖于漂亮的数据。

微软具有whitepaper该聚簇索引为等效的非聚集索引上的堆(未完全按照我上面所讨论的相同,但接近)进行比较。他们的结论基本上是在所有表格上放置聚集索引。我会尽我所能来概括他们的结果(再次,注意,他们真的比较非聚集索引在这里聚集索引 - 但我认为这是相对可比的):

  • INSERT性能:聚集索引由于堆所需的第二次写入而赢得了大约3%。
  • UPDATE性能:聚簇索引由于堆所需的第二次查找而赢得大约8%。
  • DELETE性能:聚簇索引由于需要进行第二次查找而赢得了大约18%,并且需要从IAM中为堆进行第二次删除。
  • 单个SELECT性能:聚簇索引由于堆所需的第二次查找而赢得了大约16%。
  • 范围SELECT性能:聚簇索引由于堆的随机排序而赢得大约29%。
  • 并发INSERT:由于聚簇索引的页面拆分,堆表在负载下赢得30%。
+1

这个问题今天在我脑海中浮现出来。感谢@Terrapin提出这个问题并感谢@Marc回答这个问题! 01 5月. 112011-05-01 18:53:22

+1

MS考试70461查询Microsoft SQL Server 2012 - 第15章第1课有深入的探索。 13 1月. 152015-01-13 23:28:57

  0

我似乎无法获得由您的这条语句所指示的假设提升:“对于可以(至少部分)由聚集索引满足的WHERE子句的查询,您将因为排序而出现 - 所以你不必扫描整个桌子。“我有一个1000万行的表格。 SELECT Id FROM Customer WHERE Id> X在相同的时间内执行,无论Id是否有聚集索引。怎么来的?我可以看到它是如何从表扫描转换为聚簇索引扫描的。 30 4月. 152015-04-30 07:17:40

+2

@MattiasNordqvist - 如果你只是在看时间,你做错了。由于缓存,并发访问,CPU与磁盘时间等因素,很难单独按时完成MS-SQL。查看SET STATISTICS IO ON来检查你的磁盘读取,这是提升来自哪里。其次,它将取决于返回的行数 - 如果它的比例足够高,优化器可以设想选择读取+过滤器。 30 4月. 152015-04-30 19:42:44


-2

表扫描必须检查表的每一行下面之间的性能差异。聚簇索引扫描只需要扫描索引。它不扫描表中的每条记录。这实际上就是指数的重点。

+7

-1这是错误的。聚集索引*的叶级别是该表。 14 2月. 142014-02-14 19:05:25


4

http://msdn.microsoft.com/en-us/library/aa216840(SQL.80).aspx

聚集索引扫描逻辑和物理操作者扫描参数列中所指定的簇索引。当存在可选的WHERE :()谓词时,仅返回满足谓词的那些行。如果参数列包含ORDERED子句,则查询处理器已经请求按照聚集索引对它们排序的顺序返回行的输出。如果ORDERED子句不存在,存储引擎将以最佳方式扫描索引(不保证输出被排序)。

http://msdn.microsoft.com/en-us/library/aa178416(SQL.80).aspx

表扫描逻辑和物理操作者从在Argument列中指定的表中检索的所有行。如果WHERE :()谓词出现在参数列中,则仅返回满足谓词的那些行。