【问题标题】:Why does InnoDB require clustered index upon creating a table?为什么 InnoDB 在创建表时需要聚集索引?
【发布时间】:2018-02-09 05:48:33
【问题描述】:

即使我没有主键或唯一键,InnoDB 仍会在合成列上创建集群索引,如下所述。

https://dev.mysql.com/doc/refman/5.5/en/innodb-index-types.html

那么,为什么 InnoDB 必须要求聚集索引?这里必须存在聚集索引是否有明确的原因?

在 Oracle 数据库或 MSSQL 中,我认为他们不需要这个。 另外,我认为集群索引与普通表相比也没有那么大的优势。

确实,使用集群键查找数据不需要额外的磁盘读取,并且比我没有集群索引但没有集群索引时更快,二级索引可以通过使用物理rowID查找更快。 因此,我认为没有任何理由坚持使用它。

【问题讨论】:

  • 除了您链接的文档中的描述之外,我不确定您希望我们说什么。 Innodb 的创建者做出了设计决定。如果您不喜欢它,请使用不同的表类型或 rdbms 产品。
  • @Shadow 我只是想知道他们做出这个决定的原因。我的目的是更多地了解聚集索引,而不是选择要使用的产品。
  • There are probably plenty of optimisation decisions that can be made when there are fewer choices.确定哪些关键点与开始的第一个对话有关“如果我们假设所有表都有一个聚集索引,我们可以做......”是不太可能的。
  • @PhanHoangMinh 那么您应该询问开发人员。我们只能猜测文档中写的内容。

标签: mysql sql indexing clustered-index


【解决方案1】:

其他供应商有一个“ROWNUM”或类似的东西。 InnoDB 要简单得多。它不需要那种动物,它只需要你通常想要的东西。在这两种情况下,它都是一个唯一标识行的值。这对于事务的胆量是必需的——知道要锁定哪些行等,以提供事务完整性。 (这里我就不赘述了。)

在要求(或提供)PK 以及进行某些其他简化时,InnoDB 牺牲了几个很少使用(或易于解决)的特性:多个 pk、多个聚集索引、无 pk 等。

由于“合成列”需要 6 个字节,因此即使您不使用它,最好只提供id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY。但是如果你不使用它,但确实有一个非 NULL UNIQUE 键,那么你不妨将它设为 PK。 (正如 MySQL 默认所做的那样。)

辅助键查找首先从辅助键的 BTree 中获取 PK 值。然后向下钻取主 BTree(具有由 PK 排序的数据)以查找行。因此,辅助密钥可能比使用 PK 更慢。 (通常这还不够慢。)因此,这指出了一个需要 PK的设计决策。)(其他供应商使用 ROWNUM 或其他东西来定位记录,而不是 PK。)

回到“为什么?”。 MySQL 中有许多决定,设计人员说“对于这个免费产品来说,简单性更好,我们不要费心构建一些复杂但很少使用的功能。起初没有子查询(临时表是一种解决方法)。没有视图(他们只是语法糖)没有物化视图(好吧,这可能是失败的;但它们可以被模拟)没有位图或哈希或 isam(等)索引(BTree 非常适合“全方位”使用) .

此外,通过始终将 PK 与数据“聚类”,通过 PK 的查找本质上比竞争对手更快(无需通过 ROWNUM)。 (辅助键查找可能不会更快。)

另一个区别——MySQL 在实现“索引合并”方面很晚,其中它使用两个索引,然后对结果进行 AND 或 OR。这对于 ROWNUM 可能很有效,但对于集群 PK 则不然。

(我不是 MySQL/MariaDB/Percona 开发人员,但我从 1999 年开始使用它们,并且几乎参加了所有主要的 MySQL 会议,其中内部信息经常被泄露。所以,我认为我对他们提出这个答案的想法。)

【讨论】:

  • 非常感谢您的回答。因此,原因是始终使用集群主键比竞争对手更快地进行查找(假设用户通常想要使用 PK)。也感谢您对“集群”的含义,我也想知道它。另外,我发现了另外一个原因:因为聚集索引可以存储到 InnoDB 内存中,并且可以在逻辑上检索数据,所以二级索引查找不需要额外的硬盘读取。考虑到发生数据碎片的情况,InnoDB 中的二级索引查找并不比竞争对手慢。
  • “集群”有很多含义。在我的回答中,我专注于它对 InnoDB 的 PK 的意义。 (另一个含义涉及多个服务器一起工作。)
  • "不需要额外的硬盘读取" -- 请记住,所有磁盘读取都可能缓存。也就是说,可能有也可能没有这种实际延迟。 touched 的磁盘块数(无论是在磁盘上还是在缓存中)是一个重要的指标。有了这个,应该注意哪些块可能被缓存。 (等等——这本身就是一个很长的讨论。)
猜你喜欢
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
  • 2013-08-30
  • 1970-01-01
  • 2012-10-14
  • 2021-01-14
  • 2019-06-24
  • 1970-01-01
相关资源
最近更新 更多