Index Condition Pushdown(ICP)是针对mysql使用索引从表中检索行数据时的一种优化方法。
 
原理:
在没有ICP特性之前,存储引擎根据索引去基表查找并将数据返回给mysql server,mysql server再根据where条件进行数据过滤。
有了ICP之后,在取出索引的同时,判断是否可以根据索引中的列进行where条件过滤,也就是将where的部分过滤操作放在了存储引擎层。这样就会减少上层sql层对记录的获取。
当sql使用覆盖索引时,不支持ICP优化方法。
 
ICP优化支持range、ref、eq_ref、ref_or_null类型的查询。查询优化器会给出相应的提示:Using index condition。当开启ICP后,在执行计划的extra列会显示:Using index condition。
 
ICP支持innodb、myisam表。对于innodb表,ICP只是用于辅助索引。
 
在5.6中,ICP不支持分区表。这个问题在mysql 5.7中得到解决。
 
优化器使用ICP时,server层将会把能够通过使用索引进行评估的where条件下推到storage engine层。数据访问和提取过程如下:
1) storage engine从索引中读取下一条索引元组。
2) storage engine使用索引元组评估下推的索引条件。如果没有满足where条件,storage engine将会处理下一条索引元组(回到上一步)。只有当索引元组满足下推的索引条件的时候,才会继续去基表中读取数据。
3) 如果满足下推的索引条件,storage engine通过索引元组定位基表的行和读取整行数据并返回给server层。
4) server层评估没有被下推到storage engine层的where条件,如果该行数据满足where条件则使用,否则丢弃。
 
没有ICP之前:
 
开启ICP之后,就变成:
默认是开启ICP的,手动开启/关闭ICP: 
set optimizer_switch = 'index_condition_pushdown=off';

set optimizer_switch = 'index_condition_pushdown=on';

 测试过程

1.环境准备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#mysql 5.6.25
#关闭结果缓存
mysql> set global query_cache_size=0;
mysql> set query_cache_type=off;
 
#查看表结构
mysql> show create table employees\G
*************************** 1. row ***************************
       Table: employees
Create Table: CREATE TABLE `employees` (
  `emp_no` int(11) NOT NULL,
  `birth_date` date NOT NULL,
  `first_name` varchar(14) NOT NULL,
  `last_name` varchar(16) NOT NULL,
  `gender` enum('M','F') NOT NULL,
  `hire_date` date NOT NULL,
  PRIMARY KEY (`emp_no`),
  KEY `idx_first_last_name` (`first_name`,`last_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
 
mysql>

2.开启ICP后进行测试

1
2
3
4
5
mysql> set profiling = 1;
mysql> select * from employees where first_name='Anneke' and last_name like '%sig' ;
mysql> explain select * from employees where first_name='Anneke' and last_name like '%sig' ;
mysql> show profiles;
mysql> show profile cpu,block io for query 1;

3.关闭ICP后进行测试

1
2
3
4
5
6
mysql> set optimizer_switch='index_condition_pushdown=off';
mysql> set profiling = 1;
mysql> select * from employees where first_name='Anneke' and last_name like '%sig' ;
mysql> explain select * from employees where first_name='Anneke' and last_name like '%sig' ;
mysql> show profiles;
mysql> show profile cpu,block io for query 1;

4.结果比较

开启ICP后的执行计划:执行计划中extra部分的内容是"using index condition"

1
2
3
4
5
6
mysql> explain select * from employees where first_name='Anneke' and last_name like '%sig' ;
+----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-----------------------+
| id | select_type | table     | type | possible_keys       | key                 | key_len | ref   | rows | Extra                 |
+----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | employees | ref  | idx_first_last_name | idx_first_last_name | 44      | const |  224 | Using index condition |
+----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-----------------------+

关闭ICP后的执行计划:执行计划中extra部分的内容是"using where"

1
2
3
4
5
6
mysql> explain select * from employees where first_name='Anneke' and last_name like '%sig' ;
+----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-------------+
| id | select_type | table     | type | possible_keys       | key                 | key_len | ref   | rows | Extra       |
+----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | employees | ref  | idx_first_last_name | idx_first_last_name | 44      | const |  224 | Using where |
+----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-------------+

 

开启ICP后的profile内容:Sending data部分的值是0.000212s

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> show profile cpu,block io for query 1;
+----------------------+----------+----------+------------+--------------+---------------+
| Status               | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+----------------------+----------+----------+------------+--------------+---------------+
| starting             | 0.000114 | 0.000000 |   0.000000 |            0 |             0 |
| checking permissions | 0.000007 | 0.000000 |   0.000000 |            0 |             0 |
| Opening tables       | 0.000018 | 0.000000 |   0.000000 |            0 |             0 |
| init                 | 0.000034 | 0.000000 |   0.000000 |            0 |             0 |
| System lock          | 0.000008 | 0.000000 |   0.000000 |            0 |             0 |
| optimizing           | 0.000023 | 0.000000 |   0.000000 |            0 |             0 |
| statistics           | 0.000383 | 0.000000 |   0.000000 |            0 |             0 |
| preparing            | 0.000019 | 0.000000 |   0.000000 |            0 |             0 |
| executing            | 0.000002 | 0.000000 |   0.000000 |            0 |             0 |
| Sending data         | 0.000212 | 0.000000 |   0.000000 |            0 |             0 |
| end                  | 0.000004 | 0.000000 |   0.000000 |            0 |             0 |
| query end            | 0.000004 | 0.000000 |   0.000000 |            0 |             0 |
| closing tables       | 0.000006 | 0.000000 |   0.000000 |            0 |             0 |
| freeing items        | 0.000020 | 0.000000 |   0.000000 |            0 |             0 |
| cleaning up          | 0.000011 | 0.000000 |   0.000000 |            0 |             0 |
+----------------------+----------+----------+------------+--------------+---------------+

关闭ICP后的profile内容:Sending data部分的值是0.010990s

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> show profile cpu,block io for query 1;
+----------------------+----------+----------+------------+--------------+---------------+
| Status               | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+----------------------+----------+----------+------------+--------------+---------------+
| starting             | 0.000165 | 0.000000 |   0.000000 |            0 |             0 |
| checking permissions | 0.000022 | 0.000000 |   0.000000 |            0 |             0 |
| Opening tables       | 0.000027 | 0.000000 |   0.000000 |            0 |             0 |
| init                 | 0.000039 | 0.000000 |   0.000000 |            0 |             0 |
| System lock          | 0.000008 | 0.000000 |   0.000000 |            0 |             0 |
| optimizing           | 0.000037 | 0.001000 |   0.000000 |            0 |             0 |
| statistics           | 0.000483 | 0.001000 |   0.000000 |            0 |             0 |
| preparing            | 0.000022 | 0.000000 |   0.000000 |            0 |             0 |
| executing            | 0.000002 | 0.000000 |   0.000000 |            0 |             0 |
| Sending data         | 0.010990 | 0.007999 |   0.002000 |            0 |             0 |
| end                  | 0.000009 | 0.000000 |   0.000000 |            0 |             0 |
| query end            | 0.000005 | 0.000000 |   0.000000 |            0 |             0 |
| closing tables       | 0.000008 | 0.000000 |   0.000000 |            0 |             0 |
| freeing items        | 0.000028 | 0.000000 |   0.000000 |            0 |             0 |
| cleaning up          | 0.000014 | 0.000000 |   0.000000 |            0 |             0 |
+----------------------+----------+----------+------------+--------------+---------------+

  

其它:

当sql使用覆盖索引时,不支持ICP优化方法

1
2
3
4
5
6
7
8
9
10
11
12
mysql> explain select first_name,last_name from employees where first_name='Anneke' and last_name='Porenta' ;
+----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+--------------------------+
| id | select_type | table     | type | possible_keys       | key                 | key_len | ref         | rows | Extra                    |
+----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+--------------------------+
|  1 | SIMPLE      | employees | ref  | idx_first_last_name | idx_first_last_name | 94      | const,const |    1 | Using where; Using index |
+----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+--------------------------+
mysql> explain select * from employees where first_name='Anneke' and last_name='Porenta' ;
+----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+-----------------------+
| id | select_type | table     | type | possible_keys       | key                 | key_len | ref         | rows | Extra                 |
+----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+-----------------------+
|  1 | SIMPLE      | employees | ref  | idx_first_last_name | idx_first_last_name | 94      | const,const |    1 | Using index condition |
+----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+-----------------------+

  

 

MySQL Index Condition Pushdown 原理与解析的更多相关文章

  1. MySQL Index Condition Pushdown

    Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式.[Index Condition Pushdown] ...

  2. MySQL Index Condition Pushdown(ICP) 优化

    本文是作者留下的一个坑,他去上茅坑了.茅坑是谁?你猜.

  3. 1229【MySQL】性能优化之 Index Condition Pushdown

    转自http://blog.itpub.net/22664653/viewspace-1210844/  [MySQL]性能优化之 Index Condition Pushdown2014-07-06 ...

  4. 【mysql】关于Index Condition Pushdown特性

    ICP简介 Index Condition Pushdown (ICP) is an optimization for the case where MySQL retrieves rows from ...

  5. 浅析MySQL中的Index Condition Pushdown (ICP 索引条件下推)和Multi-Range Read(MRR 索引多范围查找)查询优化

    本文出处:http://www.cnblogs.com/wy123/p/7374078.html(保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误 ...

  6. MySQL索引与Index Condition Pushdown

    实际上,这个页面所讲述的是在MariaDB 5.3.3(MySQL是在5.6)开始引入的一种叫做Index Condition Pushdown(以下简称ICP)的查询优化方式.由于本身不是一个层面的 ...

  7. MySQL ICP(Index Condition Pushdown)特性

    一.SQL的where条件提取规则 在ICP(Index Condition Pushdown,索引条件下推)特性之前,必须先搞明白根据何登成大神总结出一套放置于所有SQL语句而皆准的where查询条 ...

  8. MySQL 中Index Condition Pushdown (ICP 索引条件下推)和Multi-Range Read(MRR 索引多范围查找)查询优化

    一.ICP优化原理 Index Condition Pushdown (ICP),也称为索引条件下推,体现在执行计划的上是会出现Using index condition(Extra列,当然Extra ...

  9. MySQL 查询优化之 Index Condition Pushdown

    MySQL 查询优化之 Index Condition Pushdown Index Condition Pushdown限制条件 Index Condition Pushdown工作原理 ICP的开 ...

随机推荐

  1. IDEA 设置导出

    见附件 https://files.cnblogs.com/files/chuancheng/settings.7z

  2. 记录启用HTTPS的全过程

    因为 https 采用 ssl 加密,所以部署 https 时需要申请证书,证书的作用就是对浏览器和Web服务器双方的身份验证. 步骤1:申请证书 我们采用Let's Encrypt签发的免费证书,虽 ...

  3. HUD2102(基础bfs)

    A计划 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  4. ES之二:Elasticsearch原理

    Elasticsearch是最近两年异军突起的一个兼有搜索引擎和NoSQL数据库功能的开源系统,基于Java/Lucene构建.最近研究了一下,感觉 Elasticsearch 的架构以及其开源的生态 ...

  5. SpringBoot自动化配置之四:SpringBoot 之Starter(自动配置)、Command-line runners

    Spring Boot Starter是在SpringBoot组件中被提出来的一种概念,stackoverflow上面已经有人概括了这个starter是什么东西,想看完整的回答戳这里 Starter ...

  6. AngularJS:包含

    ylbtech-AngularJS:包含 1.返回顶部 1. AngularJS 包含 在 AngularJS 中,你可以在 HTML 中包含 HTML 文件. 在 HTML 中包含 HTML 文件 ...

  7. 用IntelliJ IDEA建maven项目,如何解决main下无法创建java源文件

    一.缺少java源文件 如下图: 现在想要在main下面增加java源文件,效果图如下所示: 首先,在main目录下新建java文件夹,就是源文件目录, 然后,右键,选择Mark Directory ...

  8. linux yum 脚本实现

    yum 位于linux /usr/bin/yum yum命令是python脚本进行编写的(python 2.6) #!/usr/bin/python2.6 import sys try: import ...

  9. 如何设置linux在出现kernel panic后自动重启 (ZT)

    Automatic reboot after Linux kernel panic http://www.syn-ack.org/centos-linux/automatic-reboot-after ...

  10. 11-18网页基础--第二部分CSS样式属性(1)

    第一课:样式属性 style 样式:style样式不仅可以直接在<body>中设置成整个网页的样式.格式:为了将样式.格式多样化,也可以将style单独抽出来,作为一个独立的个体,放在&l ...