知识卡片
InnoDB聚簇索引让二级索引必须携带主键,因此主键要尽量小
内容
大多数存储引擎把”数据存在哪”和”索引指向哪”分开处理:索引里 存的是一个指向数据物理位置的指针,无论主键还是二级索引,都是 “查到指针、再按指针去取数据”。InnoDB反过来:整张表本身就是 按主键组织的一棵索引树(聚簇索引),表中每一行数据直接就存 在这棵树的叶子节点里,而不是另外单独存一份数据、索引只是 指向它——这样按主键查询时,找到索引节点的同时就已经拿到了 完整的数据行,不需要再多跳一次,主键查询因此性能很高。这个 设计带来一个连带的、容易被忽视的后果:二级索引(非主键索引) 没法像聚簇索引那样直接存数据行,只能存”主键值”作为间接指针—— 查二级索引时,先在二级索引树里找到对应的主键值,再拿这个主键 值去聚簇索引里做第二次查找才能取到完整数据行。这意味着每一个 二级索引,内部实际上都要额外携带一份主键值的副本;如果主键 本身很大(比如用一个长字符串做主键),那么表上建的每一个二级 索引都会因此跟着变大,索引占用的存储空间和查询开销都会成倍 增加。这个连带效应说明:在InnoDB里,主键的设计从来不是一个 孤立的决定——它不只影响主键查询本身的效率,还会通过聚簇索引 这个机制,把自己的体积”摊派”到表上所有的二级索引里,这也是 “若表上索引较多,主键应当尽可能小”这条实践建议背后真正的 技术原因。
参考来源
- 位置:《高性能MySQL:第3版》第1章"MySQL架构与历史"1.5.1节
"InnoDB存储引擎"(源文件:
_epub-src/OEBPS/Text/part0008.xhtml)
- 结论依据:原文明确"InnoDB表是基于聚簇索引建立的……聚簇索引
对主键查询有很高的性能。不过它的二级索引(secondary index,
非主键索引)中必须包含主键列,所以如果主键列很大的话,其他
的所有索引都会很大。因此,若表上的索引较多的话,主键应当
尽可能的小",直接说明聚簇索引结构导致的二级索引膨胀问题及
主键设计原则。
- 原始内容:InnoDB表是基于聚簇索引建立的……聚簇索引对主键查询
有很高的性能。不过它的二级索引中必须包含主键列,所以如果
主键列很大的话,其他的所有索引都会很大。