ICP简介

Index Condition Pushdown (ICP) is an optimization for the case where MySQL retrieves rows from a table using an index. Without ICP, the storage engine traverses the index to locate rows in the base table and returns them to the MySQL server which evaluates the WHEREcondition for the rows. With ICP enabled, and if parts of the WHERE condition can be evaluated by using only fields from the index, the MySQL server pushes this part of the WHERE condition down to the storage engine. The storage engine then evaluates the pushed index condition by using the index entry and only if this is satisfied is the row read from the table. ICP can reduce the number of times the storage engine must access the base table and the number of times the MySQL server must access the storage engine.

也就说:利用索引(二级索引)来过滤一部分where条件

测试

导入数据库

wget https://launchpad.net/test-db/employees-db-1/1.0.6/+download/employees_db-full-1.0.6.tar.bz2
tar jxf employees_db-full-1.0.6.tar.bz2
cd employees_db
mysql -uroot -p < employees.sql

表结构

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 `index_bh` (`birth_date`,`hire_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

一些表数据

mysql> select @@optimizer_switch like '%index_condition_pushdown%' \G
*************************** 1. row ***************************
@@optimizer_switch like '%index_condition_pushdown%': 1
1 row in set (0.00 sec) mysql> select @@optimizer_switch like '%index_condition_pushdown%' \G
*************************** 1. row ***************************
@@optimizer_switch like '%index_condition_pushdown%': 1
1 row in set (0.00 sec) mysql> select @@query_cache_type;
+--------------------+
| @@query_cache_type |
+--------------------+
| OFF |
+--------------------+
1 row in set (0.01 sec) mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
| 300024 |
+----------+
1 row in set (0.17 sec) mysql> set profiling=1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

建立索引

alter table employees add index index_bh (`birth_date`,`hire_date`);

查询分析

mysql> explain select *   from employees where birth_date between '1955-01-01' and '1955-12-31' and datediff(hire_date,birth_date)>12300 and first_name like 'S%b%';
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+-------------+
| 1 | SIMPLE | employees | range | index_bh | index_bh | 3 | NULL | 46318 | Using where |
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+-------------+
1 row in set (0.00 sec) mysql> SET optimizer_switch='index_condition_pushdown=on';
Query OK, 0 rows affected (0.00 sec) mysql> explain select * from employees where birth_date between '1955-01-01' and '1955-12-31' and datediff(hire_date,birth_date)>12300 and first_name like 'S%b%';
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+------------------------------------+
| 1 | SIMPLE | employees | range | index_bh | index_bh | 3 | NULL | 46318 | Using index condition; Using where |
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+------------------------------------+
1 row in set (0.01 sec)

执行查询

mysql> show profiles;                                                                                                                 +----------+------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
| 1 | 0.00278025 | desc employees |
| 2 | 0.00049775 | show create table employees |
| 3 | 0.07444550 | select * from employees where birth_date between '1955-01-01' and '1955-12-31' and datediff(hire_date,birth_date)>12300 and first_name like 'S%b%' |
| 4 | 0.00027500 | SET optimizer_switch='index_condition_pushdown=off' |
| 5 | 0.12347025 | select * from employees where birth_date between '1955-01-01' and '1955-12-31' and datediff(hire_date,birth_date)>12300 and first_name like 'S%b%' |
+----------+------------+------------------------------------------------------------------------------------------------------------------------------------------------------+

从结果可以看出来开启ICP之后确实快不少

启用ICP之后,可以用索引来筛选 datediff(hire_date,birth_date)>12300 记录,不需要读出整条记录

ICP原理

如下图所示(图来自MariaDB)

1、优化器没有使用ICP时

  • 在存储引擎层,首先读取索引元组(index tuple),然后使用(index tuple)在基表中(base table)定位和读取整行数据
  • 到服务器层,匹配where条件,如果该行数据满足where条件则使用,否则丢弃
  • 指针向下一行移动,重复以上过程

2、使用ICP的时候

  • 如果where条件的一部分能够通过使用索引中的字段进行过滤,那么服务器层将把这部分where条件Pushdown到存储引擎层
  • 到存储引擎层,从索引中读取索引元组(index tuple),使用索引元组进行判断,如果没有满足where条件,则处理下一条索引元组(index tuple),只有当索引元组满足条件的时候,才会去基表中读取数据

ICP的使用条件

1、只能用于二级索引(secondary index)

2、explain显示的执行计划中type值(join 类型)为range、 ref、 eq_ref或者ref_or_null。且查询需要访问表的整行数据,即不能直接通过二级索引的元组数据获得查询结果(索引覆盖)

3、ICP可以用于MyISAM和InnnoDB存储引擎,不支持分区表(5.7将会解决这个问题)

4、ICP的加速效果取决于在存储引擎内通过ICP筛选掉的数据的比例

参考文章

https://mariadb.com/kb/en/index-condition-pushdown/

http://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html

http://blog.codinglabs.org/articles/index-condition-pushdown.html

【mysql】关于Index Condition Pushdown特性的更多相关文章

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

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

  2. MySQL 之 Index Condition Pushdown(ICP)

    简介 Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式. 当关闭ICP时,index 仅仅是data ...

  3. MySQL中Index Condition Pushdown(ICP)优化

    在MySQL 5.6开始支持的一种根据索引进行查询的优化方式.之前的MySQL数据库版本不支持ICP,当进行索引查询是,首先根据索引来查找记录,然后在根据WHERE条件来过滤记录.在支持ICP后,My ...

  4. MySQL 5.6新特性 -- Index Condition Pushdown

    Index Condition Pushdown(ICP)是针对mysql使用索引从表中检索行数据时的一种优化方法.   在没有ICP特性之前,存储引擎根据索引去基表查找并将数据返回给mysql se ...

  5. MySQL ICP(Index Condition Pushdown)特性

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

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

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

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

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

  8. MySQL Index Condition Pushdown

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

  9. MySQL Index Condition Pushdown 原理与解析

    Index Condition Pushdown(ICP)是针对mysql使用索引从表中检索行数据时的一种优化方法.   原理: 在没有ICP特性之前,存储引擎根据索引去基表查找并将数据返回给mysq ...

随机推荐

  1. 搜索 + 剪枝 --- POJ 1101 : Sticks

    Sticks Problem's Link:   http://poj.org/problem?id=1011 Mean: http://poj.org/problem?id=1011&lan ...

  2. C#实战Microsoft Messaging Queue(MSMQ)消息队列(干货)

    前言 在使用MSMQ之前,我们需要自行安装消息队列组件!(具体安装方法大家自己搜一下吧) 采用MSMQ带来的好处是:由于是异步通信,无论是发送方还是接收方都不用等待对方返回成功消息,就可以执行余下的代 ...

  3. HBase Scan Timeout-OutOfOrderScannerNextException

    最近迁移数据时需要执行大Scan,HBase集群经常碰到以下日志: Exception in thread "main" org.apache.hadoop.hbase.DoNot ...

  4. 循序渐进开发WinForm项目(1) --数据库设计和项目框架的生成

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...

  5. ASP.NET WebAPI 09 Controller的激活

    在Controller之前我们先回顾一下HttpMessageHandler通道. 在这个图中我留一个HttpContollerDispatcher没有说明.因为这个类也是继承自HttpMessage ...

  6. 「C语言」单链表/双向链表的建立/遍历/插入/删除

    最近临近期末的C语言课程设计比平时练习作业一下难了不止一个档次,第一次接触到了C语言的框架开发,了解了View(界面层).Service(业务逻辑层).Persistence(持久化层)的分离和耦合, ...

  7. android开发布局文件imageview 图片等比例缩放:

    ImageView的属性scaleType,如果等比缩放的话,就使用CenterInside,如果想固定大小的话,就CenterCrop <?xml version="1.0" ...

  8. ArrayList 与 LinkedList

    ArrayList:数组结构,插入删除的效率低,查询的效率较高. LinkedList:链接数据结构,插入删除的效率较高,查询的效率低. 两者的使用 ArrayList:适合用作添加数据,做查询. L ...

  9. has_many :through VS has_and_belongs_to_many

    user role has_and_belongs_to_many role.destroy:  关联表user_roles先删除记录,再role删除. has_many :through user. ...

  10. 再议使用Python批量裁切栅格

    曾经写过<使用Python脚本批量裁切栅格>,但今天又遇到这个情况则发现了问题.我们遇到的实际问题往往是有一个需要裁剪的影像(大块的),另外有一个矢量面,现在需要按矢量面每一个要素进行裁剪 ...