每个用户表都应该有一个聚集索引吗?
每个用户表是否应该有一个聚集索引?
聚集索引是数据库中的一种索引类型,其作用是帮助检索数据并找到匹配的行。如果在搜索条件上创建了非聚集索引,它可以帮助找到匹配的行,但需要额外的操作来获取行的数据。如果表中没有聚集索引,SQL会使用一个内部的rowId来指向数据的位置。然而,如果表上有一个聚集索引,那么这个rowId将被聚集索引中的数据值所取代。因此,读取行数据的步骤将不再需要,并且可以由索引中的数值来覆盖。
即使聚集索引在选择性方面表现不佳,如果这些键经常是请求结果的大部分或全部,将它们作为非聚集索引的叶子节点可能会有所帮助。
性能是一个重要的问题,我们需要确保优化的是正确的东西。因此,对于这个问题,我们可以考虑在表上创建一个聚集索引来提高查询性能。
每个用户表是否都应该有一个集群索引?
在SQL Server MVP Brad McGehee的观点中,他指出每个表通常都应该有一个集群索引。通常情况下,集群索引应该建立在一个递增的列上,例如自增列或者其他值递增且唯一的列。在许多情况下,主键是集群索引的理想列。
BOL也提到了这一观点,除了少数情况外,每个表都应该有一个集群索引。
之所以这样做的原因有很多,主要是因为集群索引可以在存储中对数据进行物理排序。
如果你的集群索引建立在一个递增的单列上,插入操作将按顺序在存储设备上进行,避免了页面分裂。
当索引值是唯一的时候,集群索引可以高效地查找特定的行,比如根据主键选择行的常见模式。
集群索引经常可以高效地对经常搜索范围值的列进行查询(例如between、>等)。
聚集可以加速按特定列或列进行排序的查询。
可以根据需要重建或重新组织集群索引以控制表的碎片化。
这些好处甚至可以应用于视图。
但并不是每个表都需要有一个集群索引。对于具有频繁数据更改的列、已经被其他索引覆盖的列、宽键以及GUID列来说,可能不适合使用集群索引。
如果数据始终通过非聚集索引进行访问并且RID(SQL Server内部行标识符)小于集群索引键,那么使用堆(没有集群索引的表)可能是一个罕见的原因。
因为这些和其他考虑因素,如特定应用程序工作负载,你应该仔细选择你的集群索引以获得查询的最大效益。
还要注意,当在SQL Server中的表上创建主键时,默认情况下会创建一个唯一的集群索引(如果还没有)。这意味着如果你发现一个表没有集群索引,但有一个主键(正如所有表应该有的那样),开发人员之前已经做出了这个决定。你可能需要有一个有说服力的理由来改变这种情况(我们已经看到了很多这样的理由)。在大表上添加、更改或删除集群索引需要重写整个表和任何非聚集索引,所以在大表上可能需要一些时间。
你能解释一下第三个项目“A clustered index allows for efficient queries on columns that are often searched for ranges of values (between, >, etc.)”吗?
聚集索引以这种方式工作,因为下一个更高或更低的键行保证在存储中是相邻的。因此,一旦找到第一个值,就不需要再搜索剩下的行,因为它们已经被找到了。
他们并不保证在存储中是物理相邻的。它们只保证在逻辑上是相邻的。这就是为什么需要重新组织或重建索引的原因。
很好,你是对的。没有一个索引是免受碎片化的。Technet需要更新这句话:“[...]具有连续索引值的行保证在物理上相邻。”
你提到堆是罕见的情况,但是如果你使用GUID标识符,我认为这并不少见。除了插入日期和连续ID之外,通常没有太多其他候选列符合递增、更改频率较低且访问频率相对较高的要求。
有一篇有趣的文章在这里推崇使用堆:use-the-index-luke.com/blog/2014-01/…
如果集群索引的列的值不是递增的,你会受到多大的惩罚?如果表中所有的列都是这样的,你仍然应该有一个集群索引吗?
如果你经常使用聚集表上的备用索引来查询特定的行,那么你必须进行两次索引查找,因为备用索引包含在聚集索引上使用的键。在堆上,它包含的是RID,即行的位置。
文章标题:每个用户表都应该有一个聚集索引吗?
在数据库设计中,是否为每个用户表定义一个聚集索引是一个需要仔细考虑的问题。不是所有的表都需要一个聚集索引,但在某些情况下,它可以提高性能。然而,盲目地将聚集索引应用于所有表可能会导致性能下降,特别是在使用GUID作为主键的情况下。
聚集索引是一种物理排序索引,它确定了数据在磁盘上的存储顺序。对于那些经常进行插入操作的表来说,聚集索引可能会导致性能下降,因为每次插入数据时都需要进行磁盘上的物理重新排序。
在决定是否为表定义聚集索引时,需要仔细考虑表的访问方式。如果表经常用于范围查询或排序操作,聚集索引可能会提高性能。然而,如果表主要用于插入操作,并且没有频繁的范围查询或排序需求,那么可能不需要聚集索引。
此外,使用GUID作为主键的表也需要特别注意。GUID是全局唯一标识符,它的生成是随机的,导致数据插入时不会按照特定的顺序进行排列。这意味着每次插入操作都会导致磁盘上的物理重新排序,从而影响性能。
因此,在决定是否为每个用户表定义聚集索引时,需要仔细考虑表的访问方式和具体情况。如果表经常进行范围查询或排序操作,并且不使用GUID作为主键,那么为其定义一个聚集索引可能会提高性能。然而,如果表主要用于插入操作,并且使用GUID作为主键,那么可能不需要聚集索引。
最后,需要注意的是,并非所有数据库系统都支持聚集索引,或者以这种形式支持。因此,在选择数据库系统时,也需要考虑该功能的可用性和适用性。
参考资料:
- [Stack Overflow: Should every User Table have a Clustered Index?](https://stackoverflow.com/questions/2126704)
- [When should a Clustered Index be used?](https://www.sqlservercentral.com/articles/when-should-a-clustered-index-be-used)