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

由于“ Table Scan和“ Clustered Index Scan扫描表中的所有logging,为什么聚簇索引扫描会更好?

举个例子 – 当有很多logging时,下面的性能差别是什么?

 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 

在没有聚集索引(堆表)的表中,数据页面没有链接在一起 – 因此遍历页面需要查找索引分配映射 。

然而,一个聚集表中,它的数据页是链接在一个双向链表中的 – 使得顺序扫描速度更快一些。 当然,作为交换,你有处理在INSERTUPDATEDELETE保持数据页顺序的开销。 但是,堆表需要第二次写入IAM。

如果你的查询有一个RANGE运算符(例如: SELECT * FROM TABLE WHERE Id BETWEEN 1 AND 100 ),那么一个聚集表(保证顺序)会更有效率 – 因为它可以使用索引页来find相关的数据网页。 堆将不得不扫描所有的行,因为它不能依靠sorting。

而且,当然,聚集索引可以让你做一个CLUSTERED INDEX SEEK,这对于性能来说是非常理想的…没有索引的堆总是会导致表扫描。

所以:

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

  • 对于带有WHERE子句的查询,可以(至less部分)通过聚集索引满足要求,因为sorting,所以您将不得不提前扫描整个表。

  • 对于一个不被聚集索引满足的查询,你几乎就是……唯一的区别就是顺序扫描的双向链表。 无论如何,你都不是最理想的。

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

微软有一个白皮书 ,它将聚簇索引与堆上等价的非聚簇索引进行比较(与上面讨论的不完全相同,但是很接近)。 他们的结论基本上是在所有的表格上加上一个聚集索引。 我会尽我所能来总结他们的结果(再一次,请注意,他们真的在这里比较非聚集索引和聚集索引 – 但我认为它是相对可比的):

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

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

“群集索引扫描”逻辑和物理运算符将扫描“参数”列中指定的聚簇索引。 当存在一个可选的WHERE :()谓词时,只有那些满足谓词的行被返回。 如果参数列包含ORDERED子句,则查询处理器已经请求按照聚集索引对其进行sorting的顺序返回行的输出。 如果ORDERED子句不存在,存储引擎将以最佳方式扫描索引(不保证输出被sorting)。

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

“表扫描”逻辑和物理运算符从“参数”列中指定的表中检索所有行。 如果WHERE :()谓词出现在参数列中,则只返回满足谓词的那些行。

表扫描必须检查表的每一行。 聚簇索引扫描只需要扫描索引。 它不扫描表中的每个logging。 这实际上就是指数的重点。