MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么区别?
MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么区别?
回答重点
聚簇索引:
- 索引叶子结点存储的是数据行,可以直接访问完整数据。
- 每个表只能有一个聚簇索引,通常是主键索引,适合范围查询和排序。
非聚簇索引:
- 索引叶子节点存储的是数据行的主键和对应的索引列,需通过主键才能访问完整的数据行。
- 一个表可以有多个非聚簇索引(称之为非主键索引、辅助索引、二级索引),适用于快速查找特定列的数据。
扩展知识
进一步分析
在 InnoDB 里聚簇索引就是主键索引,非聚簇索引指的是非主键索引(辅助索引、二级索引),默认情况下它们都是 B+树实现的。
以下为一个简单的 B+ 树示例图:
如果是主键索引:
- 非叶子节点存储主键和页号
- 叶子节点存储完整的数据
- 叶子节点之间有双向链表链接,便于范围查询
- 叶子节点内部有页目录,内部记录是单链表链接,通过页目录二分再遍历链表即可得到对应记录。
- B+ 树只能帮助快速定位到的是页,而不是记录。
- 页大小默认 16k,是按照主键大小排序的,所以无序的记录插入因为排序会插入到页中间,又因为容量有限会导致页分裂存储,性能比较差,所以主键要求有序。
如果是非聚簇索引:
- 和主键索引的差别就在于叶子节点仅存储索引列和主键,不包含完整行的数据。
例如一个表有 id、姓名、性别、地址等等字段,本身包含聚簇索引,此时再给姓名建立一个索引,此时的索引叶子节点存储如下图所示:
所以说不要所有查询都用 select * ,因为如果本来只需要查询索引列数据的话,直接利用二级索引就能得到所要的数据。
例如通过姓名仅查询 id 的话,直接利用姓名索引就能得到数据,通过如果图方便直接用 select * ,那就不得不通过 id 再去主键索引查找不需要的性别和地址,浪费资源,且可能伴随着很多随机 I/O。
通过二级索引查找得到 id ,再去主键索引查询的这个过程叫回表。
Comments