MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么区别?

Sherwin.Wei Lv7

MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么区别?

回答重点

聚簇索引

  • 索引叶子结点存储的是数据行,可以直接访问完整数据。
  • 每个表只能有一个聚簇索引,通常是主键索引,适合范围查询和排序。

非聚簇索引

  • 索引叶子节点存储的是数据行的主键和对应的索引列,需通过主键才能访问完整的数据行。
  • 一个表可以有多个非聚簇索引(称之为非主键索引、辅助索引、二级索引),适用于快速查找特定列的数据。

扩展知识

进一步分析

在 InnoDB 里聚簇索引就是主键索引,非聚簇索引指的是非主键索引(辅助索引、二级索引),默认情况下它们都是 B+树实现的。

以下为一个简单的 B+ 树示例图:

image.png

如果是主键索引:

  • 非叶子节点存储主键和页号
  • 叶子节点存储完整的数据
  • 叶子节点之间有双向链表链接,便于范围查询
  • 叶子节点内部有页目录,内部记录是单链表链接,通过页目录二分再遍历链表即可得到对应记录。
  • B+ 树只能帮助快速定位到的是页,而不是记录。
  • 页大小默认 16k,是按照主键大小排序的,所以无序的记录插入因为排序会插入到页中间,又因为容量有限会导致页分裂存储,性能比较差,所以主键要求有序。

如果是非聚簇索引:

  • 和主键索引的差别就在于叶子节点仅存储索引列和主键,不包含完整行的数据。

例如一个表有 id、姓名、性别、地址等等字段,本身包含聚簇索引,此时再给姓名建立一个索引,此时的索引叶子节点存储如下图所示:

image.png

所以说不要所有查询都用 select * ,因为如果本来只需要查询索引列数据的话,直接利用二级索引就能得到所要的数据。

例如通过姓名仅查询 id 的话,直接利用姓名索引就能得到数据,通过如果图方便直接用 select * ,那就不得不通过 id 再去主键索引查找不需要的性别和地址,浪费资源,且可能伴随着很多随机 I/O。

通过二级索引查找得到 id ,再去主键索引查询的这个过程叫回表。

Comments
On this page
MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么区别?