深入理解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 写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性 ...
随机推荐
- APIO2020 粉刷墙壁
考场想了 5.5 h,第一部分分死活打不出来,做到崩盘,现在重做,感觉自己就是一个sb,放学在地铁上一眼就会了.哎. 可以把一个要求看作一个长度为 \(m\) 的区间:\([l, l + m - 1] ...
- linux关闭在线登录用户
在使用电脑的时候,发现自己的电脑上有其他的用户登陆.如果其他用户用的是自己的名字,那么就能通过who去查询出来,但是如果登陆的都是root用户,那么肯定不知道是谁,所以需要我们清除他们:另外呢,如果登 ...
- 标注工具labelimg和labelme
矩形标注工具:labelimg 多边形标准工具:labelme 前者官网发布了可执行文件,后者只有python源码,如果需要编译windows exe,可以这样: pip install labelm ...
- 记一次 HBase Master is initializing 问题处理
问题 hbase shell中建立建表出错 分析 org.apache.hadoop.hbase.PleaseHoldException: Master is initializing代表Master ...
- DP-DAY3游记
问题 A: 2017夏令营第一阶段(Day3)问题A拆分数字I 题目描述 把数字N拆分一些正整数的和,问有多少种不同的方法? 例如:N=4,有1+1+1+1.1+1+2.1+2+1.1+3.2+ ...
- Sharding-JDBC使用jasypt3.0及以上版本加密数据库连接密码
本文中介绍的是基于Sharding-JDBC 4.0和jasypt 3.0及其以上版本对数据库连接密码进行加密操作 引入依赖 项目的pom.xml中引入maven依赖 <dependency&g ...
- python简单爬去前程无忧信息招聘
import sys reload(sys) sys.setdefaultencoding('utf-8') import requests import csv from BeautifulSoup ...
- ASP.NET Core Web 支付功能接入 微信-扫码支付篇(转)
原文 https://www.cnblogs.com/essenroc/p/8630730.html // 随着版本更迭,新版本可能无法完全适用,请参考仓库内的示例. 这篇文章将介绍ASP.NET C ...
- PhPMyadmin拿Shell
phpmyadmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具, --百度百科 1.入口寻找 目录扫描: 根据Linux对大小写敏感判断目标服 ...
- JavaEE在职加薪课好客租房项目实战视频教程
JavaEE在职加薪课好客租房项目实战视频教程课程介绍: 本课程采用SOA架构思想进行设计,基于目前主流后端技术框架SpringBoot.SpringMVC.Mybaits.Dubbo等来 ...