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

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

  •  76
  • Seibar  · 技术社区  · 17 年前

    由于两者 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 回复  |  直到 12 年前
        1
  •  76
  •   BanksySan    9 年前

    在没有聚集索引的表(堆表)中,数据页不会链接在一起,因此遍历页面需要 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    17 年前

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

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

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

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

        3
  •  -2
  •   DrPizza    17 年前

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