第二,B+树的叶子节点是数据阶段用了一个链表串联起来,便于范围查找 。
通过 B 树和 B+树的对比我们看出,B+树节点存储的是索引,在单个节点存储容量有限的情况下,单节点也能存储大量索引,使得整个 B+树高度降低,减少了磁盘 IO 。其次,B+树的叶子节点是真正数据存储的地方,叶子节点用了链表连接起来,这个链表本身就是有序的,在数据范围查找时,更具备效率 。因此 Mysql 的索引用的就是 B+树,B+树在查找效率、范围查找中都有着非常不错的性能 。
综上所述mysql innodb 索引选择了B+树 。
思考问题1、B+树叶子节点存的诗所有数据,如果1000万数据,那这个链表太大,不会影响性能吗?
可以利用数据页,下面有重点分析
2、InnoDB一棵B+树可以存放多少行数据?
B+Tree 的根节点和枝节点中都不会存储数据,只有叶子节点才存储数据 。搜索 到关键字不会直接返回,会到最后一层的叶子节点 。比如我们搜索 id=3,虽然在第一 层直接命中了,但是全部的数据在叶子节点上面,所以我还要继续往下搜索,一直到叶 子节点 。
举个例子:假设一条记录是 1K,一个叶子节点(一页)可以存储 16 条记录 。非叶 子节点可以存储多少个指针?
假设索引字段是 bigint 类型,长度为 8 字节 。指针大小在 InnoDB 源码中设置为 6 字节,这样一共 14 字节 。非叶子节点(一页)可以存储 1024*16 / 14 = 1170 个这样的 单元(键值+指针),代表有 1170 个指针 。
树深度为 2 的时候,有 1170^2 个叶子节点,可以存储的数据为:
1170 * 1170 * 16 = 21902400 2000万
在查找数据时一次页的查找代表一次 IO,也就是说,一张 2000 万左右的表,查询数据最多需要访问 3 次磁盘 。所以在 InnoDB 中 B+ 树深度一般为 1-3 层,它就能满足千万级的数据存储 。
二、innodb的索引分析在 InnoDB 中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表 。
上述中我们从不同维度分析了最终InnoDB 使用了 B+ 树索引模型,所以数据都是存储在 B+ 树中的 。
每一个索引在 InnoDB 里面对应一棵 B+ 树 。假设,我们有一个主键列为 ID 的表,表中有字段 k,并且在 k 上有普通索引 。
这个表的建表语句是:
create table user(id int primary key,k int not null,name varchar(16),index (k))engine=InnoDB;
表中 第一行到第五行 的 (ID,k) 值分别为 (100,1)、(200,2)、(300,3)、(500,5) 和 (600,6),两棵树的示例示意图如下 。文章插图
上图为:主健索引
文章插图
上图为:普通索引
根据上面的索引结构说明,我们来讨论一个问题:基于主键索引和普通索引的查询有什么区别?
如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索 ID 这棵 B+ 树;
如果语句是 select * from T where k=5,即普通索引查询方式,则需要先搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次 。这个过程称为回表 。也就是说,基于非主键索引的查询需要多扫描一棵索引树 。因此,我们在应用中应该尽量使用主键查询 。
B+ 树为了维护索引有序性,在插入新值的时候需要做必要的维护 。以上面这个图为例,如果插入新的行 ID 值为 700,则只需要在 R5 的记录后面插入一个新记录 。如图
文章插图
如果新插入的 ID 值为 400,就相对麻烦了,需要逻辑上挪动后面的数据,空出位置,如图 。
文章插图
而更糟的情况是,如果 R5 所在的数据页已经满了,根据 B+ 树的算法,这时候需要申请一个新的数据页,然后挪动部分数据过去 。这个过程称为页分裂 。在这种情况下,性能自然会受影响 。
除了性能外,页分裂操作还影响数据页的利用率 。原本放在一个页的数据,现在分到两个页中,整体空间利用率降低大约 50% 。当然有分裂就有合并 。
推荐阅读
- Linux系统安全攻防技术
- 大唐李世民的儿子李恪,大唐之李渊义子
- 康熙皇帝被称为什么,康熙为什么能被立为皇帝
- 杠铃卧推标准动作是什么
- 蒲公英对妇科炎症,妇科炎症如何根治
- 一个哑铃怎么练胸肌
- 游泳对皮肤的好处有哪些
- 求职|部分编制人员将额外有“补贴”,约650元,对应薪资会随之变高吗
- 卫生间对着餐厅是好是坏?
- 郭子仪李光弼团结对敌,安史之乱两大名将郭子仪