当前位置:网站首页>一文读懂什么是MySQL索引下推(ICP)
一文读懂什么是MySQL索引下推(ICP)
2022-06-30 21:10:00 【Aiky哇】
一、简介
ICP(Index Condition Pushdown)是在MySQL 5.6版本上推出的查询优化策略,把本来由Server层做的索引条件检查下推给存储引擎层来做,以降低回表和访问存储引擎的次数,提高查询效率。
二、原理
为了理解ICP是如何工作的,我们先了解下没有使用ICP的情况下,MySQL是如何查询的:
- 存储引擎读取索引记录;
- 根据索引中的主键值,定位并读取完整的行记录;
- 存储引擎把记录交给
Server层去检测该记录是否满足WHERE条件。
使用ICP的情况下,查询过程如下:
- 读取索引记录(不是完整的行记录);
- 判断
WHERE条件部分能否用索引中的列来做检查,条件不满足,则处理下一行索引记录; - 条件满足,使用索引中的主键去定位并读取完整的行记录(就是所谓的回表);
- 存储引擎把记录交给
Server层,Server层检测该记录是否满足WHERE条件的其余部分。
三、实践
先创建一张表,并插入记录
CREATE TABLE user (
id int(11) NOT NULL AUTO_INCREMENT COMMENT "主键",
name varchar(32) COMMENT "姓名",
city varchar(32) COMMENT "城市",
age int(11) COMMENT "年龄",
primary key(id),
key idx_name_city(name, city)
)engine=InnoDB default charset=utf8;
insert into user(name, city, age) values("ZhaoDa", "BeiJing", 20),("QianEr", "ShangHai", 21),("SunSan", "GuanZhou", 22), ("LiSi", "ShenZhen", 24), ("ZhouWu", "NingBo", 25), ("WuLiu", "HangZhou", 26), ("ZhengQi", "NanNing", 27), ("WangBa", "YinChuan", 28), ("LiSi", "TianJin", 29), ("ZhangSan", "NanJing", 30), ("CuiShi", "ZhengZhou", 65), ("LiSi", "KunMing", 29), ("LiSi", "ZhengZhou", 30);查看一下表记录
mysql> select * from user;
+----+----------+-----------+------+
| id | name | city | age |
+----+----------+-----------+------+
| 1 | ZhaoDa | BeiJing | 20 |
| 2 | QianEr | ShangHai | 21 |
| 3 | SunSan | GuanZhou | 22 |
| 4 | LiSi | ShenZhen | 24 |
| 5 | ZhouWu | NingBo | 25 |
| 6 | WuLiu | HangZhou | 26 |
| 7 | ZhengQi | NanNing | 27 |
| 8 | WangBa | YinChuan | 28 |
| 9 | LiSi | TianJin | 29 |
| 10 | ZhangSan | NanJing | 30 |
| 11 | CuiShi | ZhengZhou | 65 |
| 12 | LiSi | KunMing | 29 |
| 13 | LiSi | ZhengZhou | 30 |
+----+----------+-----------+------+
13 rows in set (0.00 sec)注意,这张表里创建了联合索引(name, city),假设我们想查询如下语句:
select * from user where name="LiSi" and city like "%Z%" and age > 25;3.1 不使用索引下推
在不使用索引下推的情况下,根据联合索引“最左匹配”原则,只有name列能用到索引,city列由于是模糊匹配,是不能用到索引的,此时的执行过程是这样的:
- 存储引擎根据
(name, city)联合索引,找到name值为LiSi的记录,共4条记录; - 然后根据这4条记录中的id值,逐一进行回表扫描,去聚簇索引中取出完整的行记录,并把这些记录返回给
Server层; Server层接收到这些记录,并按条件name="LiSi" and city like "%Z%" and age > 25进行过滤,最终留下("LiSi", "ZhengZhou", 30)这条记录。
画张图看一下:
3.2 使用索引下推
使用索引下推的情况下,执行过程是这样的:
- 存储引擎根据
(name, city)联合索引,找到name='LiSi'的记录,共4条; - 由于联合索引中包含
city列,存储引擎直接在联合索引中按city like "%Z%"进行过滤,过滤后剩下2条记录; - 根据过滤后的记录的id值,逐一进行回表扫描,去聚簇索引中取出完整的行记录,并把这些记录返回给
Server层; Server层根据WHERE语句的其它条件age > 25,再次对行记录进行筛选,最终只留下("LiSi", "ZhengZhou", 30)这条记录。
画张图看一下:
另外,从执行计划里也可以看到使用了索引下推(Extra里显示Using index condition)
mysql> explain select * from user where name="LiSi" and city like "%Z%" and age > 25;
+----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+----------+------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+----------+------------------------------------+
| 1 | SIMPLE | user | NULL | ref | idx_name_city | idx_name_city | 99 | const | 4 | 7.69 | Using index condition; Using where |
+----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+----------+------------------------------------+
1 row in set, 1 warning (0.00 sec)
四、使用条件
- 只能用于
range、ref、eq_ref、ref_or_null访问方法; - 只能用于
InnoDB和MyISAM存储引擎及其分区表; - 对
InnoDB存储引擎来说,索引下推只适用于二级索引(也叫辅助索引);
索引下推的目的是为了减少回表次数,也就是要减少IO操作。对于
InnoDB的聚簇索引来说,完整的行记录已经加载到缓存区了,索引下推也就没什么意义了。
- 引用了子查询的条件不能下推;
- 引用了存储函数的条件不能下推,因为存储引擎无法调用存储函数。
五、相关系统参数
索引条件下推默认是开启的,可以使用系统参数optimizer_switch来控制器是否开启。
查看默认状态:
mysql> select @@optimizer_switch\G;
*************************** 1. row ***************************
@@optimizer_switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on
1 row in set (0.00 sec)切换状态:
set optimizer_switch="index_condition_pushdown=off";
set optimizer_switch="index_condition_pushdown=on";边栏推荐
- 你我他是谁
- 利用日志服务器输出各种apache的日志的TOPN
- uniapp-生命周期/路由跳转
- sqlserver 字符串类型转换成小数或者整数类型
- 翻转链表II[翻转链表3种方式+dummyHead/头插法/尾插法]
- Flinksql两个kafka 流可以进行join么?
- Peking University ACM problems 1003:hangover
- 对多态的理解
- MySQL introduction, detailed installation steps and usage | dark horse programmer
- Analysis and proposal on the "sour Fox" vulnerability attack weapon platform of the US National Security Agency
猜你喜欢

《大厂面试》之JVM篇21问与答

RP原型资源分享-购物类App

How to move forward when facing confusion in scientific research? How to give full play to women's advantages in scientific research?

MySQL advanced 3

Radar data processing technology

centos——开启/关闭oracle

MySQL简介、详细安装步骤及使用 | 黑马程序员

Label Contrastive Coding based Graph Neural Network for Graph Classification

SQL Server 提取字符串中的纯数字

go搭建服务器基础
随机推荐
Qiao NPMS: search for NPM packages
Oracle 数据库表结构 Excel 导出
加密与解密以及OpenSSL的应用
转:用实际行动赢得别人追随
Failed to configure a DataSource: ‘url‘ attribute is not specified and no embedded datasource could
文本生成模型退化怎麼辦?SimCTG 告訴你答案
uniapp-路由uni-simple-router
Radar data processing technology
Move blog to CSDN
Understanding polymorphism
[original] unable to use the code dialog height and width to solve the screen problem
ArcGIS construction and release of simple road network data service and rest call test
修改已经上线的小程序名称
文本识别-SVTR论文解读
The 16th Heilongjiang Provincial Collegiate Programming Contest
Analysis and proposal on the "sour Fox" vulnerability attack weapon platform of the US National Security Agency
网络营销之四大误解
开发技术-使用easyexcel导入文件(简单示例)
Upgrade Kube with unknown flag: --network plugin
凤凰架构——架构师的视角