mysql 作为一个关系型数据库,在国内应用应该是最宽泛的。兴许你司应用 Oracle、Pg 等等,然而大多数互联网公司,比方我司应用得最多的还是 Mysql,重要性显而易见。
事件是这样的,上一篇对于 MySQL 基础架构的文章收回当前,有小伙伴说能不能聊聊索引?日常工作中,咱们遇到 sql 执行慢的时候,常常会收到这样的倡议:” 加个索引呗 ”。索引到底是啥呢?它为啥能进步执行效率呢?这篇咱们来聊聊~
01 索引是什么?
索引是一种数据结构,它的呈现就是为了进步数据查问的效率,就像一本书的目录。想想一本书几百页,没有目录预计找得够呛的。举个艰深点的例子,我在知乎刷到的,比喻得很妙。
咱们从小就用的新华字典,外面的声母查问形式就是聚簇索引。偏旁部首就是二级索引 偏旁部首 + 笔画就是联结索引。
索引自身也是占用磁盘空间的(想想一本书中的目录也是占用页数的,你就晓得了),它次要 以文件的模式存在于磁盘中。
1.1 索引的优缺点
长处
- 进步查问语句的执行效率,缩小 IO 操作的次数
- 创立唯一性索引,能够保障数据库表中每一行数据的唯一性
- 加了索引的列会进行排序(一本书的章节程序不就是依照目录来排嘛),在应用分组和排序子句进行查问时,能够显著缩小查问中分组和排序的工夫
毛病
- 索引须要占物理空间
- 创立索引和保护索引要消耗工夫,这种工夫随着数据量的减少而减少
- 当对表中的数据进行增删改查是,索引也要动静的保护,这样就升高了数据的更新效率
1.2 索引的分类
主键索引
一种非凡的惟一索引,不容许有空值。(主键束缚 = 惟一索引 + 非空值)
惟一索引
索引列中的值必须是惟一的,然而容许为空值。
一般索引
MySQL 中的加索引类型,没啥限度。容许空值和反复值,纯正为了进步查问效率而存在。
单列索引
没啥好说的,就是索引的列数量只有一个,每个表能够有多个单列索引。
组合索引
多列值组成一个索引,专门用于组合搜寻,其效率大于索引合并。留神,应用它的时候须要恪守 最左匹配准则。多个列作为查问条件时,组合索引在工作中很罕用。
全文索引
只能在文本内容,也就是 TEXT、CHAR、VARCHAR 数据类型的列上建全文索引。有人说创立单列索引不就完了吗?思考一种状况:当这列的内容很长时,用 like 查问就会很慢,这是就适宜建全文索引。
前缀索引
还是只能作用于文本内容,也就是 TEXT、CHAR、VARCHAR 数据类型的列上建前缀索引,它能够指定索引列的长度,它是这样写的:
// 在 x_test 的 x_name 列上创立一个长度为 4 的前缀索引
alter table x_test add index(x_name(4));
这个长度是依据理论状况来定的。长了太占用空间,短了不起成果。比方:我有个表的 x_name 的第一个字符简直都是一样的(假如都是 1),如果创立索引的长度 = 1,执行以下查问的时候就可能比原来更糟。因为数据库外面太多第一个字符 = 1 的列了,所以选的时候尽量抉择数据开始有差异的长度。
SELECT * FROM x_test WHERE x_name = '1892008.205824857823401.800099203178258.8904820949682635656.62526521254';
空间索引
MySQL 在 5.7 之后的版本反对了空间索引,而且反对 OpenGIS 几何数据模型。MySQL 在空间索引这方面遵循 OpenGIS 几何数据模型规定。
02 索引的内存模型
实现索引的形式有很多种,这里先介绍下最常见的三种:哈希表、有序数组、二叉树,其中二叉树又分为二叉查找树、均衡二叉树、B 树以及 B+ 树,从而阐明为啥 InnDB 抉择了 B+ 树?为了不便作图举例我先建个表,建表语句如下:user 有两列,一列是身份证号,还有一列是名称。
CREATE TABLE IF NOT EXISTS `user`(`id_card` INT(6) NOT NULL,
`name` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id_card`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.1 哈希表
HashMap 置信大家都用过,哈希表就是一种以键值对存储数据的构造。在 MySQL 中 key 用于存储索引列,value 就是某行的数据或者是它的磁盘地址。
用过 HashMap 的你可能晓得了,当多个 key 通过哈希函数换算之后会呈现同一个值,这种状况下就会 value 值的构造就是个链表。假如当初让你通过身份证号找名字,这时它的哈希表索引构造是这样的:
从上图可知,user2 和 user4 哈希进去的 key 值都是 M,这个时候 value 的值就是个链表。如果你要查 id_card = 66688 的人,步骤是:先将 66688 通过哈希函数算出 M,而后按程序遍历链表,找到 user2。
你可能留神到了上图中四个 id_card 的值并不是递增的,所以减少新 user 时速度会很快,往后追加就好。但又因为不是有序的,做区间查问的速度就会很慢。
所以,哈希表构造实用于只有等值查问的场景,不适宜范畴查问。
2.2 有序数组
为了解决区间查问速度慢的问题,有序数组应运而生。它的等值和范畴查问都很快。还是下面依据身份号找用户的例子,这时候的索引构造是这样的:
身份证号递增且不反复从而有以上有序数组,这是如果你要查 id_card = 66666 的用户,用二分法就能够啦,复杂度是 O(log(N))。
这数组还反对范畴查问,还是用二分查找法,如果你要查区间 [12345,66666]的用户,只须要二分查找出 id_card 大于等于 12345 且小于 66666 的用户即可。
单看查问效率,有序数组几乎完满,然而如果咱们要新增数据就很很好受了。假如你要新增 id_card = 12346 的用户,那就只能把前面的数据都往后挪一个地位,老本太高了。
所以 有序数组只实用于存储一些不怎么变的数据,比方一些过来的年份数据。
2.3 二叉搜寻树
二叉搜寻树,也称二叉查找树,或二叉排序树。其定义也比较简单,要么是一颗空树,要么就是具备如下性质的二叉树:每个节点只有两个分叉,左子树所有节点值比右子树小,每个节点的左、右子树也是一个小的二叉树,且没有健值相等的节点。
说概览有点懵,先上个图。个别的二叉搜寻树长这样:
之所以设计成二叉有序的构造是因为能够利用二分查找法,它的插入和查找的工夫复杂度都是 O(log(N)),然而最坏状况下,它的工夫复杂度是 O(n),起因是在插入和删除的时候树没有保持平衡。比方顺拐的二叉树:
所以 这种状况下,树的查问工夫复杂度都变高,而且也不稳固。
2.4 均衡二叉树
均衡二叉树也叫 AVL 树,它与二叉查找树的区别在于 均衡,它任意的左右子树之间的高度差不大于 1。我做了个比照,如下图:
这样就很开心了,依据均衡二叉树的特点。它的查问工夫复杂度是 O(log(N)),当然为了保护均衡它更新的工夫复杂度也是 O(log(N))。貌似完满?然而还有问题。
学过数据结构都晓得,工夫复杂度与树高相干。你想想假如当初有一颗 100 万节点的均衡二叉树,树高 20。一次查问须要拜访 20 个数据块。而依据计算机组成原理得悉,从磁盘读一个数据快均匀须要 10ms 的寻址工夫。PS:索引不止存在内存中,还会写到磁盘上,所以优化的外围在于缩小磁盘的 IO 次数。
也就是说,对于一个 100 万行的表,如果应用均衡二叉树来存储,独自拜访一行可能须要 20 个 10ms 的工夫,也就是 0.2s,这很好受了。
此外,均衡二叉树不反对疾速的范畴查问,范畴查问时须要从根节点屡次遍历,查问效率真心不高。
所以,大多数的数据库存储也并不应用均衡二叉树。
2.5 B 树
下面剖析咱们晓得了,查问慢是因为树高,要屡次拜访磁盘。为了让一个查问尽量少涉及磁盘。咱们能够升高树的高度,既然有二叉。那咱们多分几个叉,树的高度不就升高了?所以,这时就用到了 B 树(你心里没点吗?哈哈哈)。
在 MySQL 的 InnoDB 存储引擎一次 IO 会读取的一页(默认一页 16K)的数据量,而二叉树一次 IO 无效数据量只有 16 字节,空间利用率极低。为了最大化利用一次 IO 空间,一个简略的想法是在每个节点存储多个元素,在每个节点尽可能多的存储数据。每个节点能够存储 1000 个索引(16k/16=1000),这样就将二叉树革新成了多叉树,通过减少树的叉树,将树从高瘦变为矮胖。构建 1 百万条数据,树的高度只须要 2 层就能够(1000*1000=1 百万),也就是说只须要 2 次磁盘 IO 就能够查问到数据。磁盘 IO 次数变少了,查问数据的效率也就进步了。
B 树也叫 B- 树,一颗 m 阶(m 示意这棵树最多有多少个分叉)的 B 树。特点是:
- 每个非叶子节点并且非根节点起码有 m/2 个(向上取整),即外部节点的子节点个数起码也有 m/2 个。
- 根节点至多有两个子节点,每个内节点(非叶子节点就是内节点)最多有 m 个分叉。
- B 树的所有节点都存储数据,一个节点蕴含多个元素,比方健值和数据,节点中的健值从小到大排序。
- 叶子节点都在同一层,高度一致并且它们之间没有指针相连。
3 阶的 B 树结构如下图所示:
- 等值查问
在这样的构造下咱们找值等于 48 的数据,还是应用二分查找法。它的查问门路是这样的:数据库 1 -> 数据块 3 -> 数据块 9。一共通过三次磁盘 IO,而同样数据量状况下,用均衡二叉树存储的树高必定是更高的。它的 IO 次数显然是更高的。所以说 B 树其实是放慢了查问效率。
- 范畴查问
不晓得大家留神到没有?B 树的叶子节点,并没有指针相连。意味着如果是范畴查问,比方我查 41~ 58 的数据。
首先,二分查找法拜访:数据块 1 -> 数据块 3 -> 数据块 9,找到 41;而后再回去从根节点遍历:数据块 1 -> 数据块 3 -> 数据块 10,找到 58,一共经验了 6 次 IO 查问才算是实现,这样查问的效率就慢了很多。
它还存在以下问题:
1. 叶子节点无指针相连,所以范畴查问减少了磁盘 IO 次数,升高了查问效率。
2. 如果 data 存储的是行记录,行的大小随着列数的增多,所占空间会变大。这时,一个页中可存储的数据量就会变少,树相应就会变高,磁盘 IO 次数就会变大。
所以说,B 树还有优化的空间。
2.6 B+ 树
B+ 树其实是从 B 树衍生过去的。它与 B 树有两个区别:
- B+ 树的非叶子节点不存放数据,只寄存健值。
- B + 树的叶子节点之间存在双向指针相连,而且是双向有序链表
它的数据结构如下图所示:
由上图得悉,B+ 树的数据都寄存在叶子节点上。所以每次查问咱们都须要检索到叶子节点能力把数据查出来。有人说了,那这不变慢了吗?B 树不肯定要检索到叶子节点呀。
其实不然,因为 B+ 的非叶子节点不再存储数据。所以它能够存更多的索引,也即实践上 B+ 树的树高会比 B 树更低。从这个角度来说,与其为了非叶子结点上能存储值而抉择 B 树,倒不如抉择 B+ 树,升高树高。
咱们通过剖析来看看 B+ 树靠不靠谱。
- 等值查问
在这样的构造下咱们找值等于 48 的数据,还是应用二分查找法。它的查问门路是这样的:数据块 1 -> 数据块 3 -> 数据块 9。一共通过三次磁盘 IO,这没故障。
- 范畴查问
比方我查 41~ 49 的数据。首先二分查找拜访:数据库 1 -> 数据块 3 -> 数据块 8。一样通过了三次磁盘 IO,找到 41 缓存到后果集。
但因为叶子节点是个双向有序链表,这个时候只须要往后走。将 49 所在的数据块 9 加载到内存遍历,找到 49,查问完结,只走了 4 次磁盘 IO。
这里能够看出对于范畴查问来说,相比于 B 树要走一遍老路,B+ 树就显得高效很多。
所以,B+ 树中等值和范畴查问都反对疾速查。这样 MySQL 就抉择了 B+ 树作为索引的内存模型。
03 MySQL 的索引是如何执行的?
好了,能够作为所索引内存模型的数据结构都剖析了一遍。最终 MySQL 还是抉择了 B+ 树作为索引内存模型。那 B+ 树在具体的引擎中是怎么发挥作用的呢?一起来看看
3.1 InnDB 索引
首先是 InnDB 索引,篇幅起因,我就聊聊主键索引和一般索引。
3.1.1 主键索引
主键索引又叫聚簇索引,它应用 B+ 树构建,叶子节点存储的是数据表的某一行数据。当表没有创立主键索引是,InnDB 会主动创立一个 ROWID 字段用于构建聚簇索引。规定如下:
- 在表上定义主键 PRIMARY KEY,InnoDB 将主键索引用作聚簇索引。
- 如果表没有定义主键,InnoDB 会抉择第一个不为 NULL 的惟一索引列用作聚簇索引。
- 如果以上两个都没有,InnoDB 会应用一个 6 字节长整型的隐式字段 ROWID 字段构建聚簇索引。该 ROWID 字段会在插入新行时主动递增。
多说无益,以上面的 Student 表为例,它的 id 是主键,age 列为一般索引。
CREATE TABLE `student` (`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`age` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `index_age`(`age`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 66 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
表数据如下:
- 主键索引等值查问 sql:
select * from student where id = 38;
过程如下:
- 第一次磁盘 IO:从根节点检索,将数据块 1 加载到内存,比拟 38 < 44,走右边。
- 第二次磁盘 IO:将右边数据块 2 加载到内存,比拟 8<37<38,走左边。
- 第三次磁盘 IO:将左边数据块 6 加载到内存,比拟 37<38,38=38。查问结束,将数据返回客户端。
流程图:3 次磁盘 IO
- 主键索引范畴查问 sql
select * from student where id between 38 and 44;
后面也介绍说了,B+ 树因为叶子节点有双向指针,范畴查问能够间接利用双向有序链表。
过程如下:
- 第一次磁盘 IO:从根节点检索,将数据块 1 加载到内存,比拟 38 < 44,走右边。
- 第二次磁盘 IO:将右边数据块 2 加载到内存,比拟 8<37<38,走左边。
- 第三次磁盘 IO:将左边数据块 6 加载到内存,比拟 37<38,38=38。走左边。
- 第四次磁盘 IO:将左边数据块 7 加载到内存,比拟 38<44=44。查问结束,将数据返回客户端。
流程图:一共四次磁盘 IO
3.1.2 一般索引
- 一般索引等值查问 sql
在 InnDB 中,B+ 树一般索引不存储数据,只存储数据的主键值。比方本表中的 age,它的索引构造就是这样的:
执行以下查问语句,它的流程又是怎么的呢?
select * from student where age = 48;
应用一般索引须要检索两次索引。第一次检索一般索引找出 age = 48 失去主键值,再应用主键到主键索引中检索取得数据。这个过程称为回表。
也就是说,基于非主键索引的查问须要多扫描一遍索引树。因而,咱们应该尽量应用主键查问。
过程如下:
- 第一次磁盘 IO:从根节点检索,将数据块 1 加载到内存,比拟 48 < 54,走右边。
- 第二次磁盘 IO:将右边数据块 2 加载到内存,比拟 28<47<48,走左边。
- 第三次磁盘 IO:将左边数据块 6 加载到内存,比拟 47<48,48=48。失去主键 38。
- 第四次磁盘 IO:从根节点检索,将根节点加载到内存,比拟 38 < 44,走右边。
- 第五次磁盘 IO:将右边数据块 2 加载到内存,比拟 8<37<38,走左边。
- 第六次磁盘 IO:将左边数据块 6 加载到内存,比拟 37<38,38=38。查问结束,将数据返回客户端。
流程图:一共 6 次磁盘 IO。
3.1.3 组合索引
如果为每一种查问都设计一个索引,索引是不是太多了?如果我当初要依据学生的姓名去查它的年龄。假如这个需要呈现的概览很低,但咱们也不能让它走全表扫描吧?
然而为一个不频繁的需要创立一个(姓名)索引是不是有点节约了?那该咋做呢?咱们能够建个(name,age)的联结索引来解决呀。组合索引的构造如下图所示:
执行以下查问语句,它的流程又是怎么的呢?
select * from student where name = '二狗 5' and age = 48;
过程如下:
- 第一次磁盘 IO:从根节点检索,将数据块 1 加载到内存,比拟 二狗 5 < 二狗 6,走右边。
- 第二次磁盘 IO:将右边数据块 2 加载到内存,比拟 二狗 2 < 二狗 4 < 二狗 5,走左边。
- 第三次磁盘 IO:将左边数据块 6 加载到内存,比拟 二狗 4 < 二狗 5,二狗 5 = 二狗 5。失去主键 38。
- 第四次磁盘 IO:从根节点检索,将根节点加载到内存,比拟 38 < 44,走右边。
- 第五次磁盘 IO:将右边数据块 2 加载到内存,比拟 8<37<38,走左边。
- 第六次磁盘 IO:将左边数据块 6 加载到内存,比拟 37<38,38=38。查问结束,将数据返回客户端。
流程图:一共六次磁盘 IO
3.1.4 最左匹配准则
最左前缀匹配准则和联结索引的 索引存储构造和检索形式 是有关系的。
在组合索引树中,最底层的叶子节点依照第一列 name 列从左到右递增排列,然而 age 列是无序的,age 列只有在 name 列值相等的状况下小范畴内递增有序。
就像下面的查问,B+ 树会先比拟 name 列来确定下一步应该搜寻的方向,往左还是往右。如果 name 列雷同再比拟 age 列。然而如果查问条件没有 name 列,B + 树就不晓得第一步应该从哪个节点查起,这就是所谓的最左匹配准则。
能够说创立的 idx_name_age (name,age) 索引,相当于创立了 (name)、(name,age)两个索引。、
组合索引的最左前缀匹配准则:应用组合索引查问时,mysql 会始终向右匹配直至遇到范畴查问 (>、<、between、like) 就进行匹配。
3.1.5 笼罩索引
笼罩索引是一种很罕用的优化伎俩。因为在下面一般索引的例子中,因为查问后果所须要的数据只在主键索引上有,所以不得不回表。那么有没有可能通过索引优化,防止回表呢?比方改成这样子:
select age from student where age = 48;
在下面一般索引例子中,如果我只须要 age 字段,那是不是意味着咱们查问到一般索引的叶子节点就能够间接返回了,而不须要回表。这种状况就是笼罩索引。
看下执行打算:
笼罩索引的状况:
未笼罩索引的状况:
3.2 myisam 索引
还是下面那张 student 表,建表语句:
CREATE TABLE `student` (`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`age` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `index_age`(`age`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 66 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
3.2.1 主键索引
与 InnDB 不同的是 myisam 的数据文件和索引文件是离开存储的。它的叶子节点存的是健值,数据是索引所在行的磁盘地址。它的构造如下:表 student 的索引文件寄存在 student.MYI 中,数据文件存储在 student.MYD 中。
- 主键索引等值查问
select * from student where id = 38;
它的具体执行流程如下:
- 第一次磁盘 IO:从根节点检索,将数据块 1 加载到内存,比拟 38 < 44,走右边。
- 第二次磁盘 IO:将右边数据块 2 加载到内存,比拟 8<37<38,走左边。
- 第三次磁盘 IO:将左边数据块 6 加载到内存,比拟 37<38,38=38。失去索引所在行的内存地址。
- 第四次磁盘 IO:依据地址到数据文件 student.MYD 中获取对应的行记录。
流程图:一共 4 次磁盘 IO。
- 主键索引范畴查问
select * from student where id between 38 and 44;
过程如下:
- 第一次磁盘 IO:从根节点检索,将数据块 1 加载到内存,比拟 38 < 44,走右边。
- 第二次磁盘 IO:将右边数据块 2 加载到内存,比拟 8<37<38,走左边。
- 第三次磁盘 IO:将左边数据块 6 加载到内存,比拟 37<38,38=38。失去索引所在行的内存地址。
- 第四次磁盘 IO:依据地址到数据文件 student.MYD 中获取主键 38 对应的行记录。
- 第五次磁盘 IO:将左边数据块 7 加载到内存,比拟 38<44=44。失去索引所在行的内存地址。
- 第六次磁盘 IO:依据地址到数据文件 student.MYD 中获取主键 44 对应的行记录。
3.2.2 一般索引
在 MyISAM 中,辅助索引和主键索引的构造是一样的,没有任何区别,叶子节点的数据存储的都是行记录的磁盘地址。只是主键索引的键值是惟一的,而辅助索引的键值能够反复。
查问数据时,因为辅助索引的键值不惟一,可能存在多个领有雷同的记录,所以即便是等值查问,也须要依照范畴查问的形式在辅助索引树中检索数据。
3.3 索引的应用技巧
3.3.1 防止回表
下面说了,回表的起因是因为查问后果所须要的数据只在主键索引上有,所以不得不回表。回表必然会影响性能。那怎么防止呢?
应用笼罩索引,举个栗子:还是下面的 student,它的一条 sql 在业务上很罕用:
select id, name, age from student where name = '二狗 2';
而 student 表的其余字段应用频率远低于它,在这种状况下,如果咱们在建设 name 字段的索引的时候,并不是应用繁多索引,而是应用联结索引(name,age)这样的话再执行这个查问语句就能够依据辅助索引查问到的后果获取以后语句的残缺数据。
这样就无效防止了通过回表再获取 age 的数据。喏,这就是一个典型的用笼罩索引的优化策略缩小回表的状况。
3.3.2 联结索引的应用
联结索引,在建设索引的时候,尽量在多个单列索引上判断下是否能够应用联结索引。联结索引的应用不仅能够节俭空间,还能够更容易的应用到索引笼罩。比方下面的 student 表,我就建了 (name,age) 和 age 索引。
联结索引的创立准则,在创立联结索引的时候因该把频繁应用的列、区分度高的列放在后面,频繁应用代表索引利用率高,区分度高代表筛选粒度大。
也能够在常须要作为查问返回的字段上减少到联结索引中,如果在联结索引上减少一个字段而应用到了笼罩索引,这种状况下应该应用联结索引。
联结索引的应用
- 思考以后是否曾经存在多个能够合并的单列索引,如果有,那么将以后多个单列索引创立为一个联结索引。
- 以后索引存在频繁应用作为返回字段的列,这个时候就能够思考当前列是否能够退出到以后曾经存在索引上,使其查问语句能够应用到笼罩索引。
3.3.3 索引下推
当初我的表数据是这样的:加了一个 sex 列。
说到满足最左前缀准则的时候,最左前缀能够用于在索引中定位记录。这时,你可能要问,那些不合乎最左前缀的局部,会怎么样呢?
咱们还是以学生表的联结索引(name,age)为例。如果当初有一个需要:检索出表中“名字第一个字是二,而且年龄是 38 岁的所有男生”。那么,SQL 语句是这么写的:
select * from student where name like '张 %' and age=38 and sex='男';
依据前缀索引规定,所以这个语句在搜寻索引树的时候,只能用 ” 张 ”,找到三个满足条件的记录(图中红框数据)。当然,这还不错,总比全表扫描要好。
而后呢?当然是判断其余条件是否满足。
在 MySQL5.6 之前,只能从满足条件的记录 id=18 开始一个个回表。到主键索引上找出数据行,再比照字段
而 MySQL 5.6 引入的索引下推优化(index condition pushdown),能够在索引遍历过程中,对索引中蕴含的字段先做判断,间接过滤掉不满足条件的记录,缩小回表次数。
它的整个执行的流程图是这样的:
InnoDB 在(name,age)索引外部就判断了 age 是否等于 38,对于不等于 38 的记录,直接判断并跳过。在咱们的这个例子中,只须要对 id=18 和 id=65 这两条记录回表取数据判断,就只须要回表 2 次,这就是所谓的索引下推。
送点书
如果看到这里,喜爱这篇文章的话,请帮点个难看。微信搜寻 一个优良的废人 ,关注后回复 电子书 送你 1000+ 本编程电子书,包含 C、C++、Java、Python、GO、Linux、Git、数据库、设计模式、前端、人工智能、面试相干、数据结构与算法以及计算机根底,详情看下图。回复 1024送你一套残缺的 java 视频教程。
伟人的肩膀
- 《高性能 MySQL》
- zhuanlan.zhihu.com/p/142361798
- cnblogs.com/lianzhilei/p/11250589.html
- blog.csdn.net/qq_35190492/article/details/109257302
- time.geekbang.org/column/article/69636
- cnblogs.com/happyflyingpig/p/7662881.html
- tech.meituan.com/2014/06/30/mysql-index.html
总结
本文解说了索引是什么?它的优缺点、分类;索引的 6 种内存模型;为什么应用 B+ 树?InnDB 和 MyIsam 引擎的主键索引、一般索引、组合索引、笼罩索引都是怎么起作用的?最左匹配准则是啥?最初还聊了下应用索引的小技巧。能够说,索引相干的知识点都在这了。看完这一篇还不懂的话,你来捶我呀!
好啦,以上就是狗哥对于索引的总结。感激各技术社区大佬们的付出,如果说我看得更远,那是因为我站在你们的肩膀上。心愿这篇文章对你有帮忙,咱们下篇文章见~