深入理解MySQL索引(下)
先创建一个T表。
mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0,
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB;
insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');
然后执行
select * from T where k between 3 and 5
思考:
需要执行几次树的搜索操作,会扫描多少行?
这条SQL的执行流程
- 在k索引树上找到k=3的记录,取得ID=300;
- 再到ID索引树查到ID=300对应的R3;
- 在k索引树取下一个值k=5,取得ID=500;
- 再回到ID索引树查到ID=500对应的R4
- 在k索引树取下一个值k=6,不满足条件,循环结束。
这个过程中,回到主键索引树搜索的过程叫做 回表。这个过程回表了2次,(步骤2和4)
在这个例子中,由于查询结果所需要的数据只在主键索引上有,所以不得不回表。那么,有没有可能经过索引优化,从而避免回表的过程呢?
覆盖索引
如果执行的语句是
select ID from T where k between 3 and 5
这时候只需要查询ID的值,而ID的值已经在K索引树上了,因此可以直接获取结果并返回,不需要再回表。也就说,在这个查询里面索引k已经覆盖了我们的查询需求,我们称为覆盖索引。
因为覆盖索引可以减少回表的次数,索引使用覆盖索引是一个常用的性能优化手段。
需要注意的是,在引擎内部使用覆盖索引在索引k上其实读取了3条记录,第一次是k=3,第二次是k=5,第三次是k=6;但是对于MySQL的server层来说,他就是找引擎拿到了两条数据(3,5)因此MySQL认为扫描的行数是2.
最左前缀匹配原则
如果为每一种查询都设计一个索引,索引是不是太多了,如果要按照市民的身份证号去查他们家的家庭地址该怎么办呢?虽然这种情况出现的概率也许不高但是总不能直接全表扫描吧。
B+树这种索引结构可以利用索引的最左前缀匹配来定位记录

上图中是建立了一个联合索引 (name,age),主键还是ID。
可以发现索引项是按照name从小到大排序的。
如果是查name='张三’的ID可以直接出结果。
如果要查的是性张的ID 这时候也能用到索引。where name like '张%``查到第一个符合条件的记录是ID3,然后依次向后遍历,直到遇到name的第一个字不是张的为止。
可以看到,不只是索引的全部定义,只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以是联合索引的最左N个字段,也可以是字符串索引的最左M个字符。
那到底如何安排索引内的字段顺序呢?
这里需要考虑的是索引 的复用能力。因为可以支持最左前缀,所以当已经有了(a,b)这个联合索引后,一般不需要单独在a上建立索引,(a,b)实际上 建立的索引包含a,同样建立一个联合索引(a,b,c)就相当于建立了三个索引,分别是 (a,b) (a,c),(a,b,c); 因此通过调整索引顺序可以少维护一个索引,那么这个顺序是需要优先考虑的。
那如果使用联合查询有基于a,b各自的查询呢?
select * from T where a = 1 and b = 2
select * from T where b = 2 -- 不会走索引,而是全表扫描
select * from T where b = 2 and a = 1
select * from T where a =1 -- 使用索引
第一条SQL和第三条SQL查询的结果是一样,为什么第三条SQL也会走索引,他难道不是遵从最左前缀匹配吗?
其实,我们可以这样想,因为这两条SQL的执行结果最后是一样的,对吧,既然结果是一样的,那么位于Server层的优化器就该出场了,他来决定这条SQL用哪种方式执行起来效率最高,那当然是用索引的效率高些,所以最后第三条SQL会以第一条SQL的形式执行。
这里在说一下第一条SQL和第四条SQL走索引的不同。
用
explain select * from T where a = 1 and b = 2 --type 是 ref
explain select * from T where b = 2 --type 是 index
index:这种类型表示是mysql会对整个该索引进行扫描。要想用到这种类型的索引,对这个索引并无特别要求,只要是索引,或者某个复合索引的一部分,mysql都可能会采用index类型的方式扫描。但是呢,缺点是效率不高,mysql会从索引中的第一个数据一个个的查找到最后一个数据,直到找到符合判断条件的某个索引。
ref:这种类型表示mysql会根据特定的算法快速查找到某个符合条件的索引,而不是会对索引中每一个数据都进行一 一的扫描判断,也就是所谓你平常理解的使用索引查询会更快的取出数据。而要想实现这种查找,索引却是有要求的,要实现这种能快速查找的算法,索引就要满足特定的数据结构。简单说,也就是索引字段的数据必须是有序的,才能实现这种类型的查找,才能利用到索引。
索引下推
建一张市民表
CREATE TABLE `tuser` (
`id` int(11) NOT NULL,
`id_card` varchar(32) DEFAULT NULL,
`name` varchar(32) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`ismale` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id_card` (`id_card`),
KEY `name_age` (`name`,`age`)
) ENGINE=InnoDB
现在要查姓张的男孩年龄还必须是10岁的,SQL可以这么写
mysql> select * from tuser where name like '张 %' and age=10 and ismale=1;
这个语句在搜索 索引树的时候,只能用"张",找到第一个满足条件的记录ID3,当然这种笔全表扫描要好。然后再判断剩下的条件是否满足,在MySQL5.6版本之前只能根据name查到ID3,剩下的条件需要一次一次回表判断才能最终找出结果。但是在MySQL5.6引入下推优化,可以减少回表的次数。
5.6之前,不会向后判断age,而是直接回表查询

5.6之后,会向后判断age=10的人,然后再回表,这样就减少了回表的次数

两张图中虚线代表回表。
参考 知乎大佬 https://www.zhihu.com/question/36996520
深入理解MySQL索引(下)的更多相关文章
- 理解MySQL——索引与优化
转自:理解MySQL——索引与优化 写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存 ...
- 深入理解mysql索引
深入理解mysql索引 1 深入理解索引 1.1 索引基础理论知识: 1.2 B+树索引 1.3 哈希索引 1.4 理解B+树.哈希索引结构及区别: 1.5 理解常见索引的基本概念:主键索引.唯一索引 ...
- 【索引】理解MySQL——索引与优化
MySQL 索引 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索 ...
- Mysql高手系列 - 第22篇:深入理解mysql索引原理,连载中
Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 欢迎大家加我微信itsoku一起交流java.算法.数据库相关技术. 这是Mysql系列第22篇. 背景 使用mys ...
- 要想深入理解mysql索引?这16个点你必须要了解!
前言 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQ ...
- 深入理解MySQL索引底层数据结构
作者:IT王小二 博客:https://itwxe.com MySQL 索引相关的数据结构有两种,一种是 B+tree,一种是 Hash,那么为什么在 99.99% 的情况下都使用的是 B+tree索 ...
- 深入理解 mysql 索引
1.资源准备 FQ软件下载:蓝灯 2.红黑树模拟:https://www.cs.usfca.edu/~galles/visualization/RedBlack.html 3.B树模拟:https:/ ...
- (转)理解MySQL——索引与优化
参考资料:http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html ———————————— 全文: 写在前面:索引对查询的速度有着 ...
- 1020理解MySQL——索引与优化
转自http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html 写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性 ...
随机推荐
- 题解-CF1444C Team-Building
题面 CF1444C Team-Building 给 \(n\) 个点 \(m\) 条边,每个点有颜色 \(c_i(1\le c_i\le k)\),求有多少个颜色对两组点并后是二分图. 数据范围:\ ...
- 深度剖析目标检测算法YOLOV4
深度剖析目标检测算法YOLOV4 目录 简述 yolo 的发展历程 介绍 yolov3 算法原理 介绍 yolov4 算法原理(相比于 yolov3,有哪些改进点) YOLOV4 源代码日志解读 yo ...
- 如何写好商用PPT,计算机行业PPT模板
如何写好商用PPT,这个问题如果从0开始写那确实需要花费一番功夫,今天我不是来教你如何做PPT,而是教你如何从一个小白如何快速能套用模板,从而做出一个自己行业相关的模板,比如计算机行业PPT模板,奶茶 ...
- SQL盲注、SQL注入 - SpringBoot配置SQL注入过滤器
1. SQL盲注.SQL注入 风险:可能会查看.修改或删除数据库条目和表. 原因:未对用户输入正确执行危险字符清理. 固定值:查看危险字符注入的可能解决方案. 2. pom.xml添加依赖 ...
- SpringBoot整合RabbitMQ实践教程
1. MQ MQ(Message Queue),消息队列,是生产者和消费者模型中传递信息的容器,主要用于线程或进程之间通信. MQ主要的应用场景为:应用解耦.异步处理,流量削锋,日志处理等. ...
- vue seo 优化
预渲染prerender-spa-plugin 如果你只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染.无需使用 web 服务器实时动态编译 ...
- ASP .Net Core 中间件的使用(一):搭建静态文件服务器/访问指定文件
前言 随着Asp .Net Core的升级迭代,很多开发者都逐渐倾向于.net core开发. .net core是一个跨平台的应用程序,可以在windows.Linux.macOS系统上进行开发和部 ...
- 推荐一款最强Python自动化神器!不用写一行代码!
搞过自动化测试的小伙伴,相信都知道,在Web自动化测试中,有一款自动化测试神器工具: selenium.结合标准的WebDriver API来编写Python自动化脚本,可以实现解放双手,让脚本代替人 ...
- Python-自动化测试面试
1.以你做过的项目,举例来说一下你的自动化测试是怎么做的? 参考答案:就拿简历上的ecshop项目来说吧,在编写脚本前,我们会对系统进行评估,确认这个系统可不可以实现UI自动化,如果可以的话,就筛选出 ...
- Linux下删除文件名带有空格的文件
1.使用单引号将文件名括起来进行操作: rm '2018-08-07 17-29-48.png'