【详解】面试必问:MySQL索引底层原理(基于B+Tree)

MySQL索引为什么会失效?

【详解】面试必问:MySQL索引为什么会失效?最左匹配原则中间有间隙,为什么索引不会被命中?%开头索引为什么失效?范围查询索引为什么会失效?_CodingLJ-CSDN博客

1、案例说明

        (1)先创建t_emp这张表,然后里面插入一些数据。注意插入的数据id无序的

CREATE TABLE t_emp(
	`id` INT PRIMARY KEY,
	`name` VARCHAR(20),
	`age` INT
);

INSERT INTO t_emp VALUES(5,'d',22);
INSERT INTO t_emp VALUES(6,'d',22);
INSERT INTO t_emp VALUES(7,'e',21);
INSERT INTO t_emp VALUES(1,'a',23);
INSERT INTO t_emp VALUES(2,'b',26);
INSERT INTO t_emp VALUES(3,'c',27);
INSERT INTO t_emp VALUES(4,'a',32);
INSERT INTO t_emp VALUES(8,'f',53);
INSERT INTO t_emp VALUES(9,'v',13);

        (2)然后查询表中的数据,并查看结果顺序。

SELECT * FROM t_emp;

结果为:

         可以看出结果id是有序的,插入的时候是无序插入,查询的结果是id有序的,这是因为MySQL底层主键进行了排序,为啥排序呢?因为排序之后查询会更快!接下来看一下MySQL的索引的底层数据结构。

2、MySQL索引底层实现

       我们知道,索引在数据查询的时候加快数据查询的速度。起初底层的存储是以链表的形式进行存储。如下图:

         但查询的时候链表是从链表头部到链表尾部进行搜索。现在出现了一个问题,当数据量非常大的,链表也有成千上万个。怎么设计查询才会效率高呢?于是MySQL创建基于页的管理:分页管理,InnoDB默认的存储引擎存储的是16KB。如下图:

         分页之后,MySQL底层对页进行管理,于是出现了页目录管理,页目录的大小也是16KB。页目录存储的是每一页的第一个索引的主键id,和对应的指针p,且只存储每一页的第一个主键id和指针p,不再存储数据,通过指针指向每一页。有了页目录后,查找的时候先去页目录查找,且比较的是每一页的第一个id的值。比如id为5,在页目录中比较每一页的第一个主键值,1,4,7;4<5<7,那么直接取4开头的这一页去查询。如下图:

         经过上面的分析后,我们知道底层结构是什么样的了,其实MySQL现在默认的InnoDB存储引擎使用的索引底层数据结构就是B+Tree。如下图:

我的mysql版本是mysql5.5的,老了点。

        B+Tree是一种多路搜索查找树。B+Tree其实是B-Tree的一种优化。注意,B-Tree就是B树。使其更适合实现外存储索引结构,InnoDB就是用B+Tree实现索引结构。

B树和B+树的区别:

        下图是一个B-Tree结构,可以看出,每个结点不仅包含数据的key值,还有data值。而且每一页存储空间是有限的,如果data数据较大将会导致每一页存储的key很小,当存储的数量时会导致B-Tree的深度较大,增大了查询时的磁盘I/O次数,进而影响了查询效率。

        在B+Tree树中,所有数据记录结点都是按照键值大小按照顺序存储在同一层的叶子结点上,而非叶子结点存储的是key键的信息,这样可以大大加大每个结点的key值数量降低B+Tree的高度。

小结:

        1.B+Tree非叶子结点只存储键值信息,不存储数据。

        2.B+Tree所有叶子结点之间都有一个指针链。

        3.B+Tree数据记录在都存储在叶子结点中。

        InnoDB存储引擎中页的大小为16KB,一般表的主键类型为INT(占用4个字节)类型或者BIGINT(占用8个字节),方便排序。指针类型也分为4或者8字节,也就是说一个页的结点中大概存储1K个键值。一个深度为3的B+Tree可以维护10亿条记录。实际情况每个结点并不能填满,因此在数据库中,B+Tree高度一般都在2--4层,查找一次键值行记录一般需要1~3次IO的磁盘操作。

面试中可以这样回答:

索引的底层实际上是一个B+Tree。首先insert数据的时候,基于这个数据进行排序。排序之后以链表指针的形式链接起来。同时MySQL在底层为了进一步的优化,它是基于B+Tree的结构进行存储,对数据进行一页一页的存储,默认每页的大小为16KB,查找的时候,先在页目录上查找每页的主键值,然后找到指定页,查找数据。B+Tree只有也只有叶子结点才存储数据,非叶子结点不存储数据。站在B+Tree三层的B+Tree数据结构存储的数据近8亿或者是10亿。一般的项目就2层足够。基于主键去查的话最多动用一个I/O,因为它的顶层是常驻内存的。建表的时候一般主键使用INT类型,方便插入数据的时候底层进行排序。

这就是MySQL索引的底层数据结构。

MySQL索引为什么会失效?

【详解】面试必问:MySQL索引为什么会失效?最左匹配原则中间有间隙,为什么索引不会被命中?%开头索引为什么失效?范围查询索引为什么会失效?_CodingLJ-CSDN博客

猜你喜欢

转载自blog.csdn.net/Sunshineoe/article/details/121340471