磁盘相关知识
系统从磁盘读取数据到内存时是以磁盘块(block)为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。
InnoDB存储引擎中有页(Page)的概念,页是其磁盘管理的最小单位。InnoDB存储引擎中默认每个页的大小为16KB,可通过参数innodb_page_size将页的大小设置为4K、8K、16K,在MySQL中可通过如下命令查看页的大小:
mysql> show variables like 'innodb_page_size';
B+树的定义
- 数据只存储在叶子节点上,非叶子节点只保存索引信息
- 非叶子节点(索引节点)存储的只是一个Flag,不保存实际数据记录
- 索引节点指示该节点的左子树比这个Flag小,而右子树大于等于这个Flag
- 叶子节点本身按照数据的升序排序进行链接(串联起来)
- 叶子节点中的数据在 物理存储上是无序 的,仅仅是在 逻辑上有序 (通过指针串在一起)
B+树的作用
- 在块设备上,通过B+树可以有效的存储数据
- 所有记录都存储在叶子节点上,非叶子节点存储索引信息
- B+树含有非常高的扇出,通过超过100,在查找一个记录时,可以有效减少IO操作
B+树的扇出
- 该B+树高度为2
- 每叶子页(LeafPage)4条记录
- 扇出数为5
- 叶子节点(LeafPage)有小到大(有序)串联在一起
扇出 是每个索引节点指向每个叶子节点的指针
扇出数 = 索引节点可存储的最大关键字个数 + 1
B+树的插入操作
- B+树的插入
B+树的插入必须保证插入后叶子节点中的记录依然排序
Leaf Page满 | Index Page满 | 操作 |
否 | 否 | 直接将记录插入叶子节点 |
是 | 否 | 1.拆分LeafPage 2.将中间的节点放入到Index Page中 3.小于中间节点的记录放左边 4.大于或等于中间节点的记录放右边 |
是 | 是 | 1.拆分Leaf Page 2.小于中间节点记录放左边 3.大于或等于中间节点的放右边 4.拆分Index Page 5.小于中间节点的记录放左边 6.大于中间节点的记录放右边 7.中间节点放入上一层Index Page |
示例:
B+树初始状态如下
1.插入28-->叶子节点和索引节点都没有满-->直接将记录插入叶子节点
2.插入70-->叶子节点满了,索引节点没有满
- 拆分叶子页
- 将中间节点60放入到索引节点中
- 小于60的记录放在左边叶子节点
- 大于等于60的记录放在右边的叶子节点
3. 插入95,叶子节点和索引节点都满了
- 拆分叶子页,中间节点是85
- 小于85的记录放左边
- 大于等于85放右边
- 此时索引节点也是满的,中间索引节点为60,拆分索引页
- 小于60的记录放左边
- 大于等于60的记录放右边
- 中间的60放上一层的索引页
与B树的对比
- B树的每个节点存储了key和data,key是一条数据记录的键值,是唯一的,data存储的是数据记录除key以外的数据。而B+树只在叶子节点存储data数据,这样非叶子节点就能存储更多的key。所以B+树相较于B树来说更加的矮胖,因为索引树很大不能一次IO读取进内存,树的深度越浅,查找数据时IO的次数就越少,效率就更快。
- B+树的每个叶子节点的指针指向相邻的叶子节点,构成一个有序链表,可以按照关键码排序的次序遍历全部记录。由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树叶子节点指针为null,则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。