为什么 InnoDB 在创建 table 时需要聚簇索引?
Why does InnoDB require clustered index upon creating a table?
即使我没有主键或唯一键,InnoDB 仍会在合成列上创建聚簇索引,如下所述。
https://dev.mysql.com/doc/refman/5.5/en/innodb-index-types.html
那么,为什么 InnoDB 必须要求聚簇索引?此处必须存在聚簇索引是否有明确的理由?
在 Oracle 数据库或 MSSQL 中,我看不到他们需要这个。
另外,我也不认为簇索引与普通 table 相比有如此巨大的优势。
的确,使用聚簇键查找数据不需要额外的磁盘读取,而且比我没有但没有聚簇索引时更快,二级索引可以通过使用物理 rowID 更快地查找。
因此,我看不出有任何理由坚持使用它。
其他供应商有 "ROWNUM" 或类似的东西。 InnoDB 要简单得多。它不需要那种动物,它只需要一些您 通常 想要的东西。在这两种情况下,它都是 唯一地 标识一行的值。这是事务的核心所需要的——知道要锁定哪些行等,以提供事务完整性。 (我不会在这里讨论基本原理。)
在要求(或提供)PK 以及进行某些其他简化时,InnoDB 牺牲了几个 little-used(或容易解决的)特性:多个 pk、多个聚簇索引、无 pk 等
因为 "synthetic column" 占用 6 个字节,所以几乎总是简单地提供 id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
更好,即使您不使用它。但如果你不用它,但确实有一个 non-NULL UNIQUE
键,那你还不如把它当成 PK。 (默认情况下 MySQL。)
二级键查找首先从二级键的BTree中获取PK值。然后向下钻取主 BTree(具有按 PK 排序的数据)以找到该行。因此,辅助密钥可能比使用 PK 慢。 (通常这还不够慢。)因此,这指出了一个设计决策需要一个PK。)(其他供应商使用ROWNUM ,或其他东西来定位记录,而不是 PK。)
回到"Why?"。在 MySQL 中有许多决定,其中设计师说 "simplicity is better for this free product, let's not bother building some complex, but little-used feature. At first there were no subqueries (temp tables were a workaround). No Views (they are only syntactic sugar). No Materialized Views (OK, this may be a failing; but they can be simulated). No bit-mapped or hash or isam (etc) indexing (BTree is very good for "all-around" 用法)。
此外,通过始终 "clustering" 与数据的 PK,通过 PK 进行的查找本质上比竞争更快(不通过 ROWNUM)。 (辅助键查找可能不会更快。)
另一个区别 -- MySQL 实施 "index merge" 的时间很晚,其中它使用两个索引,然后对结果进行 AND 或 OR。这对 ROWNUM 很有效,但对集群 PK 无效。
(我不是 MySQL/MariaDB/Percona 开发人员,但我从 1999 年开始使用它们,并且参加过几乎所有主要的 MySQL 会议,这些会议的内部信息经常被泄露。所以,我我认为我对他们的想法有足够的洞察力来提出这个答案。)
即使我没有主键或唯一键,InnoDB 仍会在合成列上创建聚簇索引,如下所述。
https://dev.mysql.com/doc/refman/5.5/en/innodb-index-types.html
那么,为什么 InnoDB 必须要求聚簇索引?此处必须存在聚簇索引是否有明确的理由?
在 Oracle 数据库或 MSSQL 中,我看不到他们需要这个。 另外,我也不认为簇索引与普通 table 相比有如此巨大的优势。
的确,使用聚簇键查找数据不需要额外的磁盘读取,而且比我没有但没有聚簇索引时更快,二级索引可以通过使用物理 rowID 更快地查找。 因此,我看不出有任何理由坚持使用它。
其他供应商有 "ROWNUM" 或类似的东西。 InnoDB 要简单得多。它不需要那种动物,它只需要一些您 通常 想要的东西。在这两种情况下,它都是 唯一地 标识一行的值。这是事务的核心所需要的——知道要锁定哪些行等,以提供事务完整性。 (我不会在这里讨论基本原理。)
在要求(或提供)PK 以及进行某些其他简化时,InnoDB 牺牲了几个 little-used(或容易解决的)特性:多个 pk、多个聚簇索引、无 pk 等
因为 "synthetic column" 占用 6 个字节,所以几乎总是简单地提供 id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
更好,即使您不使用它。但如果你不用它,但确实有一个 non-NULL UNIQUE
键,那你还不如把它当成 PK。 (默认情况下 MySQL。)
二级键查找首先从二级键的BTree中获取PK值。然后向下钻取主 BTree(具有按 PK 排序的数据)以找到该行。因此,辅助密钥可能比使用 PK 慢。 (通常这还不够慢。)因此,这指出了一个设计决策需要一个PK。)(其他供应商使用ROWNUM ,或其他东西来定位记录,而不是 PK。)
回到"Why?"。在 MySQL 中有许多决定,其中设计师说 "simplicity is better for this free product, let's not bother building some complex, but little-used feature. At first there were no subqueries (temp tables were a workaround). No Views (they are only syntactic sugar). No Materialized Views (OK, this may be a failing; but they can be simulated). No bit-mapped or hash or isam (etc) indexing (BTree is very good for "all-around" 用法)。
此外,通过始终 "clustering" 与数据的 PK,通过 PK 进行的查找本质上比竞争更快(不通过 ROWNUM)。 (辅助键查找可能不会更快。)
另一个区别 -- MySQL 实施 "index merge" 的时间很晚,其中它使用两个索引,然后对结果进行 AND 或 OR。这对 ROWNUM 很有效,但对集群 PK 无效。
(我不是 MySQL/MariaDB/Percona 开发人员,但我从 1999 年开始使用它们,并且参加过几乎所有主要的 MySQL 会议,这些会议的内部信息经常被泄露。所以,我我认为我对他们的想法有足够的洞察力来提出这个答案。)