【问题标题】:Why are primary keys supposed to be clustered indexes?为什么主键应该是聚集索引?
【发布时间】:2017-08-01 13:27:10
【问题描述】:

我了解表上的唯一一个聚集索引定义了行的物理排序方式,例如在表中

==================================
            Contacts
==================================
 ID (P.K.) | FirstName | LastName
==================================
    1      | 'Donald'  | 'Trump'
----------------------------------
    2      | 'Crooked' | 'Hillary'
----------------------------------
    3      | 'Crazy'   | 'Bernie'

意味着这 3 条记录按上面显示的顺序物理存储。但我不明白为什么这有帮助。也许在没有间隙的自动递增主键的情况下,就像上面的例子,这有助于查询像

SELECT FirstName+LastName FROM Contacts WHERE ID=2

因为如果ID=2 发生在O(1) 时间,物理排序允许查找(例如通过索引获取数组的元素)。但是如果表是这样的

==================================
            Contacts
==================================
 ID (P.K.) | FirstName | LastName
==================================
    1      | 'Donald'  | 'Trump'
----------------------------------
    89     | 'Crooked' | 'Hillary'
----------------------------------
    12309  | 'Crazy'   | 'Bernie'

那么物理排序不允许O(1)查找;我们能做的最好的就是O(log(n))

那么为什么我们需要主键来定义行的物理顺序呢?

【问题讨论】:

  • 您并不总是希望聚集索引成为主键。这不是必需的,只有默认值几乎总是最符合逻辑的,主键也是聚集索引。
  • 在您的第一个示例中或一般情况下,我不确定聚集索引查找本身是否为 O(1)。聚集索引只是意味着一旦在索引中找到项目,实际项目就在那里。在非聚集索引中,即使找到了项目,我们仍然需要在聚集索引中进行查找以找到实际记录(如果我的术语有些偏差,请原谅)。
  • 不知道为什么这被否决或标记为不清楚。这是一个有效的问题,我很清楚 OP 在问什么。答案肯定很长,因为它需要大量关于索引的信息,但这个问题本身对我来说似乎很合理。也许以前有人问过,但不值得一票恕我直言。
  • 您正在描述哈希索引,这些索引仅在 SQL Server 中允许用于内存优化表。正常的,基于磁盘的索引只能是 B 树或列存储(堆根本不是索引)。 B-tree 有O(log(n)),列存储可能更糟。但据我所知,即使是哈希索引也不能保证O(1),尽管有时它可能会提供。
  • @SeanLange 这太宽泛了。答案将是有关该主题的教程。 user7127000 应该读一些。这个例子甚至没有什么特别之处。另外不幸的是,这个问题与一些基础知识相矛盾(参见 cmets),包括它的前提是错误的。

标签: sql sql-server tsql database-design relational-database


【解决方案1】:

SQL Server 中聚集索引的意义不在于“物理排序”,而是行数据在 B 树的叶页中可用,从而避免了额外的查找。子树成本与非聚集 B 树索引相同:O(log n)。

物理排序实际上是对聚集索引中实际发生的事情的抽象。 extents 中的页面按分配顺序存储,不一定按聚集索引键排序。索引键排序在索引分配映射和指针链中维护,每个页面都指向下一个(不一定是相邻的)页面。在页面内,行也是按分配顺序写入和存储的,而不是键顺序,并且除非页面拆分,否则顺序不会改变。重建索引时,页面本身会被重新使用,但在重建之间不会自动维护顺序。

主键不一定是聚集索引的最佳选择。这两个概念相互正交。

【讨论】:

    猜你喜欢
    • 2012-12-21
    • 2020-10-08
    • 2010-12-17
    • 2011-05-15
    • 2012-12-30
    • 2013-08-30
    • 2011-06-03
    • 1970-01-01
    • 2020-11-06
    相关资源
    最近更新 更多