达在之前已经分享过Innodb数据存储结构知识,但是都是基于理论原理知识理解,今天利用Innodb文件解析工具ruby进行探索Innodb真实的存储结构。
索引原理过程:【Mysql】 InnoDB引擎深入 - 数据页 | 聚集索引_innodb的聚集索引的数据插入_Survivor001的博客-CSDN博客
Innodb_ruby工具的安装过程也分享过,这里就不阐述了,具体的使用方法,可以查看官网git上面的介绍:Home · jeremycole/innodb_ruby Wiki · GitHub
1、场景描述
这里我创建了简单的一些表:project用来验证不同的理论原理知识:
project 表约2.3w笔数据:
主键索引:project_id
唯一索引:index(`tenantsid`, `code`)
简单说下innodb_space语法:
innodb_space
从命令行使用的基础知识。有两种方法可以开始innodb_space
。
针对单个空间文件(ibdata 或 .ibd):
选项 | 参数 | 描述 |
---|---|---|
-F | <文件名> | 加载表空间文件(系统或表) |
针对将自动加载每个表文件的表空间文件的系统表空间:
选项 | 参数 | 描述 |
---|---|---|
-s | <文件名> | 加载系统表空间文件(例如ibdata1) |
-T | <表名> | 使用给定的表名称。 |
-I | <索引名称> | 使用给定的索引名称 |
注:使用innodb_space查看空间数据需要进入到mysql数据存储目录,我的目录:
/usr/local/mysql/data
2、通过Innodb_space查看系统表空间信息
innodb_space -s ibdata1 system-spaces;
pages:总数据页数量,这里project表,一共使用到了704个 page页
indexes:总索引个数,project表我这里就是聚簇索引和唯一索引,分别就是PRIMARY主键,index(`tenantsid`, `code`)索引。
3、指定表查看索引空间信息
innodb_space -s ibdata1 -T firestation/project space-indexes;
id :索引ID,相同的ID表示是同一个索引
root:当前索引的根page页编号 ,可以看出来
fseg:类型,page的说明
used:索引使用到了多少page页,比如PRIMARY的叶子类型中为95,表明使用到了95个page页来存储数据(因为聚簇索引叶子节点存储了数据信息)
allocated:分配了多少page
fill_factor:page使用占比 :used / allocated
这里表示:
PRIMARY 索引树使用使用了1个root节点,该节点根page编号为3,leaf节点数据为95个page,实际分配了96个数据页。这里可以看出来,PRIMARY索引树是一个2层的多叉树结构:
二级索引 index:1个root节点,page编号为7,leaf节点为42个page,实际分配了96个page,也是一个2层多叉树
1、查看节点page空间信息
已经知道了大致的索引结构了,现在可以详细查看一下指定page页信息
(1)查看主键PRIMARY root页面空间信息
innodb_space -s ibdata1 -T firestation/project -p 3 page-records
这里可以看到在查看了page为3(PRIMARY索引的root页)的页信息后,一共出来95个page信息,对应了上述表述的95个leaf page,同时默认按照主键ID从小到大排序。
之前理论知识也说过了,目录页会记录最小索引列编号,来作为目录检索,比如查询34000,那就是在33819~34232区间,指向page 6 号数据页里面,这个时候就会去6号page页检索。
所以理论上来说,page5 页中应该是存储了33649~33818之间的数据,下面来验证下
2、查看指定leaf-page空间信息
innodb_space -s ibdata1 -T firestation/project -p 5 page-records
这个打印出来内容比较多,因为所有数据都被展示了,这里我截取下前后id的信息:
这里可以看到首个数据是33649 , 结尾数据是33818,同时也发现了PRIMARY索引的leaf节点里面是有真实数据信息的。但是非叶子节点只有索引列信息,也就是主键ID。
(2)同样操作查看二级索引index空间信息
可以看出来二级索引page数量明显少于聚簇索引page,因为二级索引是不存储其他业务数据字段信息的,所以每个page能存储更多的索引列信息。
同时可以发现联合索引,在non-leaf节点中存储了联合索引列,tenantsid 和 code两个字段信息,且优先索引列顺序,同时优先对tenantsid进行排序,然后对code进行排序。这也正对了前面说到的最左原则特性。
然后看看,leaf节点信息:
可以看出来在二级索引的leaf节点中,是没有完整的数据信息的,处理索引列数据,还存储了主键id信息。这也验证了前面说到的,二级索引查询完成后会通过主键ID查询聚簇索引树。
到这里基本上已经完全了解了Innodb索引数据存储原理了
有个问题?
为什么前面查看系统空间发现project总共使用了704个page,但是通过index空间查看使用到的page数量远小于这个数。
查看系统page使用和分布:
可以看出来,处理真实使用到索引数之外,还会有其他page存储数据,比如缓存、元空间信息等等,后续再详细分享。