Mysql索引(四)
1、B树:B树即平衡查找树,一般理解为平衡多路查找树,也称为B-树、B_树。是一种自平衡树状数据结构,能对存储的数据进行O(log n)的时间复杂度进行查找、插入和删除;
1)每个节点占用一个盘块的磁盘空间;
2)一个节点上有n个升序排序的关键字和n+1个指向子树根节点的指针p,指针存储的是子节点所在的磁盘块的地址。以上图为例:每个节点有2个关键字,指向3棵子树。从根节点开始,关键字为17 35,p1指针指向的子树的数据范围为小于17,p2指针指向的子树的数据范围为17~35,p3指针指向的子树的数据范围为大于35;
如果我们要查索引关键字为29的数据,步骤如下:
- 根据根节点找到磁盘块1,读入内存(磁盘I/O操作第1次)。比较关键字29在区间(17,35),找到磁盘块1的指针P2
- 根据P2指针找到磁盘块3,读入内存(磁盘I/O操作第2次)。比较关键字29在区间(26,30),找到磁盘块3的指针P2
- 根据P2指针找到磁盘块8,读入内存(磁盘I/O操作第3次)。在磁盘块8中的关键字列表中找到关键字29
问题:
1)B树的每个节点都有data域,这无疑增大了节点大小;
2)因为磁盘IO一次读出的数据量大小是一个固定值,如果你的data数据和我的关键字一起的话,那一个节点所能存的关键字就少了;
3)所以每次读取的就少,IO次数就要增多,其中,磁盘的IO耗时是远大于在内存中的任何操作;
2、B+树:B+树在B树的基础上做了进一步的优化,使其更加适合实现外存索引结构。上面的B树的每个节点不仅包含数据的索引值,也包含了数据的data值,B+树在此基础上只包含了索引
1)每一个节点就是每一页数据,而B+树只包含索引值,这就意味着B+树可以存更多的索引;
2)所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储索引值信息,这样可以大大加大每个节点存储的索引值数量,降低B+树的高度
InnoDB的底层数据结构就是B+树,其中主页节点是常驻内存的,检索的方式同B树,但是载入内存的大小就减少了很多,对比B树,它的优点如下:
1) 非叶子节点data,只存储索引,可以放更多的索引
2) 所有叶子节点之间都有一个链指针(顺序访问指针,可以提高访问的性能),比如检索大于36的数据,通过索引找到36所在的位置之后,然后直接读取指针就可以拿到全部数据
3) 数据记录都存放在叶子节点中(磁盘)中,只有找到之后才加载到内存中
InnoDB存储引擎页的默认大小是16KB,一般表的主键类型是int,也就是4bytes或者bigint 8bytes,按照bigint来计算,指针类型也一般为6bytes,也就是说根节点一个页中大概存储16KB/(8B+6B)=1170个键值,假设叶子节点的一个页(主要存data的节点)的数据大小为1kb,那么大概就可以存16kb/1kb = 16条数据。也就是说,如果B+树的索引高度为3,那么可以维护的记录数量为1170 * 1170 * 16 = 21902400条数据,当数据量超过2000w条的时候,mysql的性能会急剧下降。实际情况中每个节点可能不能填充满,因此在数据库中,B+Tree的高度一般都在2 ~ 4层。MySQL的InnoDB存储引擎在设计时是将根节点常驻内存的,也就是说查找某一键值的行记录时最多只需要1~3次磁盘I/O操作
B+树的索引是存在父子节点冗余的,就是因为这些冗余索引,索引就可以提高了数据检索的速度。就算是全表扫描也是直接走的叶节点之间的指针