MySQL索引的数据结构B+树
存储引擎
在介绍索引之前先简单介绍一下存储引擎,因为在数据库中,存储引擎决定着数据和索引的存储方式与文件格式。
- InnoDB存储引擎:MySQL默认的存储引擎,每张表的数据与索引存放在同一文件中,主键索引是聚簇索引,底层采用B+树的数据结构。
- MyISAM存储引擎:每张表的数据与索引存放在不同文件中(.MYD和.MYI),主键索引是非聚簇索引,底层也是采用B+树的数据结构。
- Memory存储引擎:这种存储引擎将数据与索引存放在内存中,所以重启MySQL数据会丢失,它底层采用的是hash的数据结构。MySQL自带的performance_schema数据库就是使用的该存储引擎。
本文中只介绍InnoDB的聚簇索引的具体B+树结构
B+树
不多废话,直接上图:
上图是一个简单的三阶三层的B+树。所谓三阶代表了每个非叶子节点有多少个往下指的指针,有三个就是三阶。下面我们看一下 InnoDB的B+树存储了哪些信息:
- 非叶子节点:由向下指的指针与索引列的值交叉组成,B+树相较于B-树,非叶子节点并不会存放索引列的行数据,因此可以存放更多的索引信息;
- 叶子节点:由索引列的值与其行数据组成,叶子节点不会存储指针。
优势
上面只是简单画了一个三阶的B+树,实际MySQL中每个节点会固定存放4KB的数据,不管是叶子节点还是非叶子节点都是4KB大小。这样设计的原因也非常简单,操作系统在读取磁盘是以页为单位,而一页的大小就是4KB,保证一次读取可以将整个节点读取进内存,当然MySQL默认是一次读取12KB的数据。
现在,让我们粗略计算一下一个三层的B+树可以支持多少数据量的表的索引:
假设我们的索引列是一个int类型,所以索引列的值占4字节,64位系统的指针占8字节,又因为非叶子节点的指针与索引列的值交替出现,那么一个非叶子节点大概可以有341(4096 / 12)个向下的指针,两层的非叶子节点就有11万多个向下指的指针。
再估算一下非叶子节点,假设一条行数据占400字节,4KB可以存放10条行数据,乘上11万,轻松上百万。所以一个三阶的B+树支持百万级数据量的表是很轻松的,也就意味着从百万级数据中做查询只需要三次IO。