MySQL-B+树索引结构
1、存储单元
-
磁盘:最小单元是扇区,一个扇区的大小是 512个字节
-
文件系统:最小单元是块,一个块的大小是 4K
-
InnoDB存储引擎:最小单元称之为页,一个页的大小是16K
2、B+树存储结构
mysql数据库中,table表中的记录都是存储在页中。假如一行数据的大小约为1K字节,那么按 16K / 1K = 16,可以计算出一页大约能存放16条数据。
B+树存储结构如图所示:
数据页除了可以存放数据(叶子节点),还可以存放健值和指针(非叶子节点),当然他们是有序的。这样的数据组织形式,我们称为索引组织表。
B+ 树是如何检索记录?
- 首先找到根页,其实每张表的根页位置在表空间文件中是固定的,即page number=3的页
- 找到根页后通过二分查找法,定位到id=5的数据应该在指针P5指向的页中
然后再去page number=5的页中查找,同样通过二分查询法即可找到id=5的记录。
查看指定表的索引信息
mysql> SELECT b.name, a.name, index_id, type, a.space, a.PAGE_NO FROM information_schema.INNODB_SYS_INDEXES a, information_schema.INNODB_SYS_TABLES b WHERE a.table_id = b.table_id AND a.space <> 0 and b.name like '%ada%';
3、计算B+树的高度
3.1 查询表中index ID 和 page number信息
mysql> select b.NAME, a.NAME, a.INDEX_ID, a.PAGE_NO from information_schema.innodb_indexes as a join information_schema.innodb_tables as b on a.table_id=b.table_id;
+-----------------------+-----------------+----------+---------+
| NAME | NAME | INDEX_ID | PAGE_NO |
+-----------------------+-----------------+----------+---------+
| test/t1 | i_id | 163 | 5 |
| test/t1 | GEN_CLUST_INDEX | 162 | 4 |
+-----------------------+-----------------+----------+---------+
2 rows in set (0.00 sec)
3.2 ibd文件存储格式
某个表的idb文件是按照page页,一块一块存储的,innodb引擎默认 page 页大小16k。
查看表 t1 的 ibd 文件大小
[root@localhost test]# ll -h t1.ibd
-rw-r----- 1 mysql mysql 128K 1月 12 21:31 t1.ibd
通过 ibd 文件大小可知,一共有 128k/16k=8 page页
innodb引擎 page 页结构图
3.3 计算某一个表中索引高度
在 3.1 中查询到表 t1 的 i_id 索引所在的 page number 是 5,在 ibd 文件中 page 页是从 0 开始计算的,所以 i_id 索引信息保存在第 6 个 page 页中。从 3.2 结构中,可知在页头的 page_level 和 page_index_id 位置。
通过hexdump操作系统命令分析ibd文件,查看索引高度。
查看hexdump命令选项用法:
[root@localhost test]# hexdump --help
-n 长度 只解释输入的指定长度个字节
-s 偏移 跳过开头指定长度个字节
计算索引高度,偏移量offset=16k*5+38(文件头字节数)+26(页头跳过的字节数)=81984 Byte
通过如下命令可知,在 ibd 文件中存储的信息,以16进制表示。
[root@localhost test]# hexdump -s 81984 -n 10 t1.ibd
0014040 0000 0000 0000 0000 a300
001404a
可知 page_level(2字节)是 0000 。所以该索引高度为 1 。
page_index_id(8字节)是 00
00 0000 0000 a3
00 ,转换10进制为163,和 3.1 中查询结果一致。
4、一颗B+树可以存放的数据量
假设B+树的深度为2
这棵B+树的存储总记录数 = 根节点指针数 * 单个叶子节点记录条数
那么指针数如何计算?
假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,这样一共14字节。
那么一个页中能存放多少这样的组合,就代表有多少指针,即 16384 / 14 = 1170。那么可以算出一棵高度为2 的B+树,能存放 1170 * 16 = 18720 条这样的数据记录。
同理:
高度为3的B+树可以存放的行数 = 1170 * 1170 * 16 = 21902400
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程