在前面的文章"MySQL索引原理"中,有介绍到一些基本的树形结构,以及他们的对比和为什么选择B+树存储MySQL底层索引数据,这里我们聊聊InnoDB底层存储。
我们都知道MySQL底层是采取的B+树存储,那InnoDB底层的具体结构是怎样的呢?怎么存储的呢?首先,要了解InnoDB底层存储,我们需要知道InnoDB底层最小单元,以及磁盘的最小单元,当我们了解了他们就能进一步的知道底层存储是怎么样的。
存储单元
在持久化存储系统中,有几个比较重要的存储单元需要我们去了解。
磁盘:磁盘的存储单元是扇区,也是磁盘最小存储单位,一个扇区大小是512字节(0.5K)
文件系统:文件系统最小存储单元是块,一个块的大小是4096字节(4K)
InnoDB:InnoDB存储引擎最小存储单元是页,一个页的大小是16384字节(默认)(16K)
在数据的整个存储过程中,扇区、文件块、Page页的关系如下:
InnoDB引擎存储页
在InnoDB引擎中,数据的存储单元是page页,默认是16384字节,我们可以通过命令:show variables like'innodb_page_size';
来查看这个参数的大小,或者通过命令设置这个参数的大小,不过我们一般不会去设置他,就使用官方默认的大小16384字节(16K)。
也就是说,InnoDB引擎最小存储单元是page页,每一页存储16K数据;在实际使用中,往往数据是成千上万的,存储这些数据需要一个好的存储结构,而InnoDB引擎为我们设计了B+树很好的解决了这个问题。
B+树是一种多路平衡树,我们可以理解B+树的每个节点就是一个page页,每个节点存储16K的数据。其中B+树非叶子结点存储键值和指针,叶子结点存放数据,这两类数据在存储上都是有序的。这里,拿一个之前讲过的一个图验证一下。
如上图:假设我们查找id=8的数据(假设上图是聚簇索引B+树结构)。
首先找到根页,而这个根页怎么找呢?这里设计一个知识点:InnoDB中B+树的根页是常驻内存的,引擎可以很快的找到具体B+树的根页
然后通过根页和备选值8进行二分查找,找到id=8的数据是在指针P1指向的Page=2的页中,此时会去找到Page=2的页
再然后通过备选值8进行二分查找,找到id=8的数据是在指针P3指向的Page=6中,此时会去找到Page=6的页
最后,找到Page=6的page页,通过二分查找匹配到了id=8的数据项,之后load到内存并且过滤后返回给客户端
以上,就是B+树索引一条数据的大致流程。注意,这里只是做一个举例,实际page页数据不可能是只有3条数据,而是(Total = 16384字节 / 每条数据字节数)条数据。
InnoDB可以存储多少条数据呢?
在InnoDB引擎中,一个page页能够存储16K数据,一个主键类型的INT占用4字节(或者一个BIGINT占用8字节),另外INT和BIGINT的指针类型也会占用4/8字节,那么一个B+树节点(Page页)能够存储:16384/(8字节+8字节)=1024条数据(估值)。
另外,我们也知道非叶子结点存储的是键值和指针,最终的叶子结点才是数据,假设B+树有3层,则3层的B+树可以存储:1024 * 1024 * 1024 = 1073741824 约10亿条数据,其实这已经超出了单台MySQL的存储性能极限了。
一般MySQL存储的层数都是在2-3层,而B+数根页都会在内存中缓存,所以如果是聚簇索引在检索一条数据时,最多会走1-3次IO操作;如果是非聚簇索引,则依据回表做相应的增加IO次数。
InnoDB怎么获取主键索引B+树的高度呢?
由上面的推断我们可以知道,一般B+树的高度其实就在1-3层,下面从另外一个层面证明这个结论。在InnoDB的表空间文件中,约定page number为3的代表主键索引的根页,而在根页偏移量为64的地方存放了该B+树的page level。如果page level为1,则树高为2,page level为2,则树高为3。
如上图,看到表xxl_job_log
的主键索引根页的page number均为3,而其他的二级索引page number为4。因为主键索引B+树的根页在整个表空间文件中的第3个页开始,所以可以算出它在文件中的偏移量:16384*3=49152(16384为页大小)。
另外根据《InnoDB存储引擎》中描述在根页的64偏移量位置前2个字节,保存了page level的值,因此我们想要的page level的值在整个文件中的偏移量为:16384*3+64=49152+64=49216,前2个字节中。
下来我们用hexdump工具,查看表空间文件指定偏移量上的数据:
linetem表的page level为2,B+树高度为page level+1=3;
region表的page level为0,B+树高度为page level+1=1;
customer表的page level为2,B+树高度为page level+1=3;
参考文章
https://www.cnblogs.com/leefreeman/p/8315844.html