代码之家  ›  专栏  ›  技术社区  ›  Seibar

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

  •  67
  • Seibar  · 技术社区  · 16 年前

    既然两者都是 Table Scan 和A Clustered 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
    
    3 回复  |  直到 8 年前
        1
  •  76
  •   BanksySan    8 年前

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

    但是,一个集群表有 data pages linked in a doubly linked list -使顺序扫描更快一点。当然,作为交换,您有处理使数据页保持有序的开销 INSERT , UPDATE DELETE . 但是,堆表需要对IAM进行第二次写入。

    如果您的查询有 RANGE 操作员(例如: SELECT * FROM TABLE WHERE Id BETWEEN 1 AND 100 ,那么集群表(按保证的顺序)将更有效-因为它可以使用索引页来查找相关的数据页。堆必须扫描所有行,因为它不能依赖于排序。

    当然,聚集索引允许您执行聚集索引查找,这对于性能来说是非常理想的…没有索引的堆总是会导致表扫描。

    所以:

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

    • 对于带有 WHERE 子句可以(至少部分)满足聚集索引的要求,因为排序的原因,您会提前出来——所以您不必扫描整个表。

    • 对于一个不能被聚集索引所满足的查询,您甚至可以……再次强调,唯一的区别是用于顺序扫描的双链接列表。无论哪种情况,你都是次优。

    • 为了 插入 , 更新 删除 堆可能赢,也可能不赢。堆不必维护顺序,但需要对IAM进行第二次写入。我认为相对的性能差异可以忽略不计,但也相当依赖于数据。

    微软有 whitepaper 它将聚集索引与堆上的等效非聚集索引进行比较(与我上面讨论的不完全相同,但已关闭)。他们的结论基本上是在所有表上放置一个聚集索引。我将尽最大努力总结它们的结果(再次注意,这里他们确实在比较非聚集索引和聚集索引——但我认为这是相对可比的):

    • 插入 性能:由于堆需要第二次写入,聚集索引将赢得约3%。
    • 更新 性能:由于堆需要第二次查找,聚集索引将赢得约8%。
    • 删除 性能:由于需要第二次查找和第二次从IAM中删除堆,聚集索引将赢得约18%。
    • 单一的 SELECT 性能:由于堆需要第二次查找,聚集索引将赢得约16%。
    • 范围 选择 性能:由于堆的随机排序,聚集索引赢得约29%。
    • 同时发生的 插入 :由于聚集索引的页拆分,堆表在加载时会赢30%。
        2
  •  4
  •   Stu    16 年前

    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

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

        3
  •  -2
  •   DrPizza    16 年前

    表扫描必须检查表的每一行。聚集索引扫描只需要扫描索引。它不会扫描表中的所有记录。这就是指数的意义所在。