说下 MySQL 回表?

#每天一道面试题# 49

#悟空拧螺丝# 2021-09-02

回表查询:先到普通索引上定位主键值,再到聚集索引上定位行记录,它的性能较扫一遍索引树低(一般情况下)。

详细说明

一般我们自己建的索引不管是单列索引还是联合索引,都称为普通索引,相对应的另外一种就是聚簇索引。 每个普通索引就对应着一颗独立的索引B+树,索引 B+ 树的节点仅仅包含了索引里的几个字段的值以及主键值。

根据索引树按照条件找到了需要的数据,仅仅是索引里的几个字段的值和主键值,如果用 select * 则还需要很多其他的字段,就得走一个回表操作,根据主键再到主键的聚簇索引里去找,聚簇索引的叶子节点是数据页,找到数据页里才能把一行数据的所有字段值提取出来。

假设 select * from table order by a,b,c 的语句,(table 有 abcdef 6 个字段),首先得从联合索引的索引树里按照顺序 a、b、c 取出来所有数据,接着对每一条数据都根据主键到聚簇索引的查找,其实性能不高。

有时候 MySQL 引擎会觉得用了既用了联合索引和聚簇索引来查找指定的字段,太慢了,那不不如直接全表扫描得了,只用聚集索引就行。

聚簇(聚集)索引补充

只有一个聚集索引,聚簇索引的叶子节点存储行记录。根据聚簇索引的 key 查找是非常快的。

(1)如果表定义了主键,则主键就是聚集索引;

(2)如果表没有定义PK,则第一个 not NULL unique 列是聚集索引;

(3)否则,InnoDB 会创建一个隐藏的 row-id 作为聚集索引。