本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~
Github地址
大家好,我是大彬~
今天给大家分享MySQL的索引下推。
索引条件下推,也叫索引下推,英文全称Index Condition Pushdown
,简称ICP。
索引下推是MySQL5.6新添加的特性,用于优化数据的查询。
在MySQL5.6之前,通过使用非主键索引进行查询的时候,存储引擎通过索引查询数据,然后将结果返回给MySQL server层,在server层判断是否符合条件。
在MySQL5.6及以上版本,可以使用索引下推的特性。当存在索引的列做为判断条件时,MySQL server将这一部分判断条件传递给存储引擎,然后存储引擎会筛选出符合MySQL server传递条件的索引项,即在存储引擎层根据索引条件过滤掉不符合条件的索引项,然后回表查询得到结果,将结果返回给MySQL server。
可以看到,有了索引下推的优化,在满足一定的条件下,存储引擎层会在回表查询之前对数据进行过滤,可以减少存储引擎回表查询的次数。
假设有一张用户信息表user_info,有三个字段name, level, weapon(装备)
,建立联合索引(name, level)
,user_info表初始数据如下:
id | name | level | weapon |
---|---|---|---|
1 | 大彬 | 1 | 键盘 |
2 | 盖聂 | 2 | 渊虹 |
3 | 卫庄 | 3 | 鲨齿 |
4 | 大铁锤 | 4 | 铁锤 |
假如需要匹配姓名第一个字为"大",并且level为1的用户,SQL语句如下:
SELECT * FROM user_info WHERE name LIKE "大%" AND level = 1;
那么这条SQL具体会怎么执行呢?
下面分情况进行分析。
先来看看MySQL5.6以前的版本。
前面提到MySQL5.6以前的版本没有索引下推,其执行过程如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Im7Cn9ZO-1679667598502)(http://img.topjavaer.cn/img/索引下推1-7.png)]
查询条件name LIKE
不是等值匹配,根据最左匹配原则,在(name, level)
索引树上只用到name
去匹配,查找到两条记录(id为1和4),拿到这两条记录的id分别回表查询,然后将结果返回给MySQL server,在MySQL server层进行level
字段的判断。整个过程需要回表2次。
然后看看MySQL5.6及以上版本的执行过程,如下图。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3qBhNnuZ-1679667598505)(http://img.topjavaer.cn/img/索引下推2-10.png)]
相比5.6以前的版本,多了索引下推的优化,在索引遍历过程中,对索引中的字段先做判断,过滤掉不符合条件的索引项,也就是判断level是否等于1,level不为1则直接跳过。因此在(name, level)
索引树只匹配一个记录,之后拿着此记录对应的id(id=1)回表查询全部数据,整个过程回表1次。
可以使用explain查看是否使用索引下推,当Extra
列的值为Using index condition
,则表示使用了索引下推。
从上面的例子可以看出,使用索引下推在某些场景下可以有效减少回表次数,从而提高查询效率。
码字不易,如果觉得对你有帮助,可以点个赞鼓励一下!
最后给大家分享一个Github仓库,上面有大彬整理的300多本经典的计算机书籍PDF,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~
Github地址