最近,在瑞典 MySQL 用户组 (SMUG) 期间,我举办了一场专门讨论MySQL InnoDB 主键的会议。
我忘了提一个很多人都不知道的细节,但Jeremy Cole 已经指出了。
当我们定义二级索引时,二级索引将主键作为索引最右侧的列。它是默默添加的,这意味着它不可见,但用于指向聚集索引中的记录。
这是一个具有由多列组成的主键的表的示例:
CREATE TABLE `t1` (
`a` int NOT NULL,
`b` int NOT NULL,
`c` int NOT NULL,
`d` int NOT NULL,
`e` int NOT NULL,
`f` varchar(10) DEFAULT 'aaa',
`inserted` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(`a`,`b`,`c`) ) ENGINE=InnoDB;
这是表的内容(只有 2 条记录):
SELECT * FROM t1;
+---+---+---+----+----+-----+---------------------+
| a | b | c | d | e | f | inserted |
+---+---+---+----+----+-----+---------------------+
| 1 | 2 | 3 | 4 | 5 | abc | 2024-02-11 17:37:16 |
| 7 | 8 | 9 | 10 | 11 | def | 2024-02-11 17:37:26 |
+---+---+---+----+----+-----+---------------------+
现在让我们为 f 列创建一个辅助键:
ALTER TABLE t1 ADD INDEX f_idx(f);
然后,该键将包含主键作为辅助索引上最右侧的列:
橙色填充的条目是隐藏条目。
让我们在该索引的 InnoDB 页面上验证这一点:
事实上,我们可以看到主键列(红色)包含在辅助索引(紫色)的每个条目中。
当我们在二级索引中包含主键或主键的一部分时,只有主键索引中最终缺失的列才会作为最右侧的隐藏条目添加到二级索引中。
b
让我们创建一个缺少列的二级索引:
ALTER TABLE t1 ADD INDEX sec_idx (`d`,`c`,`e`,`a`);
该列b
确实将被添加为索引最右侧的隐藏列。我们来验证一下:
b
从上面我们可以看到,确实添加了column的值。第二条记录也是如此:
如果我们查看InnoDB源代码,也有这样的注释:
但是,如果我们在二级索引中只使用主键的前缀部分,会发生什么呢?
咱们试试吧:
CREATE TABLE `t1` (
`a` varchar(10) NOT NULL DEFAULT 'aaaaaaaaaa',
`b` varchar(10) NOT NULL DEFAULT 'bbbbbbbbbb',
`c` int NOT NULL DEFAULT '1',
`f` varchar(10) DEFAULT NULL,
PRIMARY KEY (`a`,`b`,`c`),
KEY `sec_idx` (`c`,`f`,`a`(2))
) ENGINE=InnoDB
SELECT * FROM t1;
+------------+------------+---+-----+
| a | b | c | f |
+------------+------------+---+-----+
| aaaaaaaaaa | bbbbbbbbbb | 1 | abc |
| ccccccccc | dddddddddd | 2 | def |
+------------+------------+---+-----+
我们可以看到a
二级索引中只使用了该列的2个字符。
如果我们检查 InnoDB 页面,我们可以注意到,事实上,完整的列也将被添加为二级索引最右侧的隐藏部分:
所以InnoDB需要有完整的PK,可见或隐藏在二级索引中。
这是不常为人所知的事情。但我们希望这篇博文能够澄清这一点。
享受 MySQL 和 InnoDB...当然,不要忘记使用主键!
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。