【问题标题】:Clustered indexes SQL Server聚集索引 SQL Server
【发布时间】:2012-04-15 12:09:02
【问题描述】:

我有 Oracle 背景,在 Oracle 中为每个表使用“索引组织表”(IOT) 听起来不合理,我从未真正见过这种情况。在 SQL Server 中,我工作的每个数据库,每个表上都有一个聚集索引,这与 IOT(概念上)相同。

这是为什么呢?是否有任何理由到处使用聚集索引?在我看来,它们只适用于少数情况。

谢谢

【问题讨论】:

  • 这是DBA-SE 上的一个相关问题,其中包含一些信息和几个链接,您可以继续阅读。 Performance of Non Clustered Indexes on Heaps vs Clustered Indexes
  • 可能是熟悉 Oracle 和 SQL Server 的人回答的最佳问题。 Database Administrators 可能是一个更好的位置。
  • 另外,建议您将此问题移至 dba.se。它有两个 cmets 和一个来自 DBA.SE 常客的(纯属巧合的)答案,而没有任何其他发帖人实际上发现聚集索引和 IOT 实际上存在显着差异。

标签: sql-server database


【解决方案1】:

聚集索引与索引组织表并不完全相同。对于 IOT,每个字段都必须参与 IOT 密钥。 SQL Server 上的聚集索引不必是唯一的,也不必是主键。

聚集索引在 SQL Server 上被广泛使用,因为几乎总是有一些自然排序可以使常用查询更加高效。 Oracle 中的 IOT 承载了更多的包袱,因此它们并没有那么有用,尽管它们可能比它们通常被认为的更有用。

从历史上看,SQL Server 6.5 或 7.0 IIRC 之前的真正旧版本不支持行级锁定,只能锁定在表或页面级别。通常会使用聚集索引来确保写入分散在表的物理存储周围,以最大程度地减少页面锁的争用。但是,SQL Server 6 几年前就停止了支持,因此存在此问题的应用程序将仅限于少数遗留系统。

【讨论】:

  • 我一般不介意维度表(小表)上的聚集索引。然而,在事实表中,我不确定这是一个好主意,它会减慢加载速度和全面扫描速度。在几乎所有情况下,自然排序都是基于时间的,通常是加载数据的顺序。
  • @Younes - 聚集索引在事实表上并没有多大用处,因为大多数查询都涉及表扫描。也许对于不支持分区的版本(例如 2012 B.I. 版),您可能希望在日期或期间列上使用聚集索引来最小化加载或归档操作的 I/O。具有日期范围的查询也可以通过使用范围扫描操作使用聚集索引来减少 I/O。
【解决方案2】:

如果没有聚集索引,您的表将被组织为一个堆。这意味着插入的每一行都添加到表末尾的数据页中。此外,随着行的更新,如果更新的数据比以前大,它们会移动到表末尾的数据页。

什么时候最好没有聚集索引

如果您的表需要尽可能快的插入,但会牺牲更新和读取速度,那么没有聚集索引可能适合您。一个例子是,如果您有一个用作队列的表,例如,许多插入稍后会被读取并移动到另一个表。

聚集索引

聚集索引根据聚集索引中的列组织表中的数据。如果你聚集在错误的东西上,例如唯一标识符,这可能会减慢速度(见下文)。

只要您的聚集索引位于最常用于搜索的值上,并且它是唯一的并且不断增加,您就可以从聚集索引中获得一些惊人的性能优势。例如,如果您有一个名为 USERS 的表,您通常在其中根据 USER_ID 查找用户数据,那么在 USER_ID 上进行集群将加快所有这些查找的性能。这只是减少了获取数据所需读取的数据页的数量。

如果您的聚集索引中有太多键,这也会减慢速度。

聚簇索引的一般规则:

不要聚集在任何 varchar 列上。

在 INT IDENTITY 列上进行聚类通常是最好的。

根据您经常搜索的内容进行分类。

基于 UniqueIdentifiers 的聚类

在索引中使用唯一标识符时,它们的效率极低,因为没有自然的排序顺序。基于索引的 b 树结构,在使用 uniqueidentifiers 时,您最终会得到极其碎片化的索引。在重建或重组后,它们仍然极为分散。所以你最终会得到一个较慢的索引,由于碎片,最终在内存和磁盘上非常巨大。同样在 uniqueidentifier 的插入中,您更有可能在索引上出现页面拆分,从而减慢您的插入速度。通常,唯一标识符对索引来说是个坏消息。

总结

我的建议是,每个表都应该有一个聚集索引,除非有充分的理由不这样做(即表作为队列运行)。

【讨论】:

  • 这证实了我对聚集索引的理解。我可以理解在具有有限行数的查找表上具有索引。符合要求。基本上,堆用于不断增长的事实表,并且在插入时自然排序。一直困扰我的是你用“唯一标识符聚类”描述的那个,我继承了一个数据库,其中一个在 2B 行的表上正在增长!这对我来说从来没有意义!最重要的是,它有一个自动化的工作来重建它。谢谢,现在开始很多事情都有意义了。
【解决方案3】:

我不知道为什么大多数时候你更喜欢堆而不是聚集索引。使用聚类,您可以免费获得一个您选择的索引。大多数情况下,这是主键(您可能无论如何都想强制执行它!)。

堆主要用于特殊情况。

【讨论】:

    【解决方案4】:

    我们在关系数据库中使用主键,通常关系是通过这些主键建立的。大多数人习惯将第一个字段命名为 TableID 并将其设为主键。当您在查询中加入两个或更多表时,如果使用聚集索引,您将获得最快的结果。

    【讨论】:

      猜你喜欢
      • 2012-10-01
      • 2018-05-08
      • 2014-12-21
      • 2010-11-23
      • 2019-02-23
      • 2014-04-27
      • 2013-03-22
      • 2013-08-20
      相关资源
      最近更新 更多