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. JDK 8 - java.util.HashMap 实现机制分析

    官方文档对 HashMap 的定义: public class HashMap<K,V> extends AbstractMap<K,V> implements Map< ...

  2. html5 日常小结

    HTML5新标签汇总 1.  html5新的 (input type=类型) 元素 <input type="number" name="quantity" ...

  3. 浅析TCP /UDP/ IP协议

    互连网早期的时候,主机间的互连使用的是NCP协议.这种协议本身有很多缺陷,如:不能互连不同的主机,不能互连不同的操作系统,没有纠错功能.为了改善这种缺点,大牛弄出了TCP/IP协议.现在几乎所有的操作 ...

  4. L2-005. 集合相似度(set使用)

    L2-005. 集合相似度 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定两个整数集合,它们的相似度定义为:Nc/Nt*1 ...

  5. mycat sequence

    数据库方式原理在数据库中建立一张表,存放sequence名称(name),sequence当前值(current_value),步长(increment int类型每次读取多少个sequence,假设 ...

  6. 在U盘分区安装Kali并引导live CD 教程以及常见的注意事项

    Kali Linux作为强大的全能渗透系统,把它制成Live CD基本算是必备技能了,但是官方提供的文档虽然简单,但是整个U盘都会被占用,确实是有点可惜,结合网上提供的一些思路加上自己的经验,向大家讲 ...

  7. 类型:Java;问题:eclipse配置maven;结果:eclipse配置maven

    eclipse配置maven 下面跟大家分享的是eclipse配置maven的方法. 方法/步骤 安装maven之前,要先安装jdk及配置JAVA_HOME环境变量.JDK1.4以上. 下载maven ...

  8. DAY13-前端之jQuery

    jQuery jQuery介绍 jQuery是一个轻量级的.兼容多浏览器的JavaScript库. jQuery使用户能够更方便地处理HTML Document.Events.实现动画效果.方便地进行 ...

  9. eclipse中。安装findbugs java检测工具

    问题提出: 当我们编写完代码,做完单元测试等各种测试后就提交正式运行,只能由运行的系统来检测我们代码是否有问题了,代码中隐藏的错误在系统运行的过程中被发现后,然后再来进行相应的修改,那么后期修改的代价 ...

  10. day69-oracle 22-DBCA

    只涉及到数据库的管理,不涉及到数据库的开发.不涉及到写SQL程序或者是写增删改查,不涉及到这些东西,也不涉及到事务. 你在安装oracle的时候它自动帮你创建一个数据库.