为什么在MariaDB中添加另一个非聚簇索引时主键不是聚簇索引

Why the primary key is not the clustered index if another non clustered index is added in MariaDB

您好,我有一个 table 通过以下查询创建的 MariaDB 版本 10.5.9

CREATE TABLE `test` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `status` varchar(60) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `test_status_IDX` (`status`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 

我一直认为默认情况下主键是聚集索引,它还定义了 table 中行的顺序,但这里似乎选择了状态索引作为聚集索引。为什么会发生这种情况,我该如何改变它?

MariaDB [test]> select * from test;
+----+--------+
| id | status |
+----+--------+
|  2 | cfrc   |
|  5 | hjr    |
|  1 | or     |
|  3 | test   |
|  6 | verve  |
|  4 | yes    |
+----+--------+
6 rows in set (0.001 sec)

假设 SELECT 的结果将按 dB 引擎中的任何列排序是不安全的。如果您希望进行排序,则应始终使用 ORDER BY col [ASC|DESC]。我看到记录按添加顺序显示,但在 deletions/insertions 等之后可能会发生变化,因此不应依赖。有关详细信息,请参阅 here

@aprsa 是对的我错误地假设结果将与聚集索引的顺序相同但在这种情况下(使用 INNODB)状态索引用于查询的评估所以这就是为什么它看起来是 'sorted' 按状态。如果我 select id 则使用主索引并且结果似乎是 'sorted' by id。在另一个引擎中,这可能不是真的。

那个特定的 table 由 2 个 BTree 组成:

  • 数据,按PRIMARY KEY排序。是的,它是聚类的,顺序为 1,2,3,...

  • 二级索引,按status排序。每个二级索引都包含一个 PK 的副本,这样它就可以进入另一个 BTree 以获取其余的列(不是说还有更多!)。也就是说,BTree 相当于一个 2 列 table 和 PRIMARY KEY(status) 加上一个 id.

注意输出的顺序是 status。我必须假设它决定简单地按顺序读取二级索引来提供结果。

是的,如果您想要特定的顺序,您必须指定一个ORDER BY。您绝不能假设我刚才讨论的细节。谁知道,明天可能会有其他事情发生,例如 in-memory 以其他方式对信息进行加扰的“散列”!

(此答案适用于 MySQL 和 MariaDB。但是,MariaDB 已经在玩 MySQL 尚未采用的散列游戏。警告!或简单地添加一个 ORDER BY.)