聚簇索引和非聚簇索引(主键索引和非主键索引)
- 聚簇索引: 聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。聚簇索引将索引和数据行放到了一块,找到索引也就找到了数据。因为无需进行回表操作,所以效率很高。
- 回表查询:InnoDB 中,对于主键索引,只需要走一遍主键索引的查询就能在叶子节点拿到数据。而对于普通索引,叶子节点存储的是 key + 主键值,因此需要再走一次主键索引,通过主键索引找到行记录,这就是所谓的回表查询,先定位主键值,再定位行记录。
- InnoDB中必然且只会有一个聚集索引,一般是主键,如果没有主键,就会优先选择非空的唯一索引,如果唯一索引页没有,就会创建一个隐藏的 row_id 作为聚集索引。
- 优点:由于它将索引和数据保存在同一个B+树中,所以查找效率高,又由于叶子节点间双向链表的存在,是它对主键的排序查找和范围查找速度也非常快;
- 缺点:对表进行修改的速度较慢,因为为了保证表中记录的物理顺序和索引的顺序一致,会把记录插到数据页(叶子节点)的相应位置,所以会产生数据重排,而且插入新记录时为了维持B+树的特性,会频繁的分裂调整,影响了整体插入效率。
- 所以建议使用聚簇索引的场景是需要进行排序或范围查找的场景,比如实现电子邮箱获取用户邮件时,如果不使用聚簇索引,则每封邮件都可能产生一次磁盘IO,如果采用聚簇索引,根据用户ID来聚集数据,那么只需要从磁盘读取少量的数据页就可以获得某个用户全部的邮件了。(where id > #{maxId})
(聚簇索引的存储不是物理上连续的,而是逻辑上连续的,这样可以降低维护成本。每张表只能有一个聚簇索引,因为数据页只能按照一棵B+树来排序)
- 非聚簇索引(非主键索引) :它将数据存储和索引分开,找到索引后,需要通过对应的地址找到对应的数据行。MyISAM 的索引方式就是非聚簇索引。
- 缺点:当通过非聚簇索引来查找数据时,首先遍历找到对应的叶子节点,也就找到了聚簇索引的主键,然后通过聚簇索引找到对应的数据。所以它需要两次索引查找,效率相对较低,这是它的。
- 优点:插入记录时不会引起数据顺序的重组。所以建议使用非聚簇索引的场景是频繁更新的列。
走普通索引,一定会出现回表查询吗?
不一定,如果查询语句所要求的字段全部命中了索引,那么就不必再进行回表查询就能拿到所有的请求数据。
很容易理解,有一个 user 表,主键为 id,name 为普通索引,则再执行:select id, name from user where name = ‘joonwhee’ 时,通过name 的索引就能拿到 id 和 name了,因此无需再回表去查数据行了。