0926MySQL中ICP索引下推
转自 http://blog.itpub.net/22664653/viewspace-1678779/
分类: MySQL
Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式。
a 当关闭ICP时,index 仅仅是data access 的一种访问方式,存储引擎通过索引回表获取的数据会传递到MySQL Server 层进行where条件过滤。
b 当打开ICP时,如果部分where条件能使用索引中的字段,MySQL Server 会把这部分下推到引擎层,可以利用index过滤的where条件在存储引擎层进行数据过滤,而非将所有通过index access的结果传递到MySQL server层进行where过滤.
优化效果:ICP能减少引擎层访问基表的次数和MySQL Server 访问存储引擎的次数,减少io次数,提高查询语句性能。
二 原理
Index Condition Pushdown is not used:
1 Get the next row, first by reading the index tuple, and then by using the index tuple to locate and read the full table row.
2 Test the part of the WHERE condition that applies to this table. Accept or reject the row based on the test result.
Index Condition Pushdown is used
1 Get the next row s index tuple (but not the full table row).
2 Test the part of the WHERE condition that applies to this table and can be checked using only index columns.
If the condition is not satisfied, proceed to the index tuple for the next row.
3 If the condition is satisfied, use the index tuple to locate and read the full table row.
4 est the remaining part of the WHERE condition that applies to this table. Accept or reject the row based on the test result.
三 实践案例
a 环境准备
数据库版本 5.6.16
关闭缓存
set query_cache_size=0;
set query_cache_type=OFF;
测试数据下载地址
b 当开启ICP时
- mysql> SET profiling = 1;
- Query OK, 0 rows affected, 1 warning (0.00 sec)
- mysql> select * from employees where first_name='Anneke' and last_name like '%sig' ;
- +--------+------------+------------+-----------+--------+------------+
- | emp_no | birth_date | first_name | last_name | gender | hire_date |
- +--------+------------+------------+-----------+--------+------------+
- | 10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 |
- +--------+------------+------------+-----------+--------+------------+
- 1 row in set (0.00 sec)
- mysql> show profiles;
- +----------+------------+--------------------------------------------------------------------------------+
- | Query_ID | Duration | Query |
- +----------+------------+--------------------------------------------------------------------------------+
- | 1 | 0.00060275 | select * from employees where first_name='Anneke' and last_name like '%sig' |
- +----------+------------+--------------------------------------------------------------------------------+
- 3 rows in set, 1 warning (0.00 sec)
此时情况下根据MySQL的最左前缀原则, first_name 可以使用索引,last_name采用了like 模糊查询,不能使用索引。
c 关闭ICP
- mysql> set optimizer_switch='index_condition_pushdown=off';
- Query OK, 0 rows affected (0.00 sec)
- mysql> SET profiling = 1;
- Query OK, 0 rows affected, 1 warning (0.00 sec)
- mysql> select * from employees where first_name='Anneke' and last_name like '%sig' ;
- +--------+------------+------------+-----------+--------+------------+
- | emp_no | birth_date | first_name | last_name | gender | hire_date |
- +--------+------------+------------+-----------+--------+------------+
- | 10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 |
- +--------+------------+------------+-----------+--------+------------+
- 1 row in set (0.00 sec)
- mysql> SET profiling = 0;
- Query OK, 0 rows affected, 1 warning (0.00 sec)
- mysql> show profiles;
- +----------+------------+--------------------------------------------------------------------------------+
- | Query_ID | Duration | Query |
- +----------+------------+--------------------------------------------------------------------------------+
- | 2 | 0.00097000 | select * from employees where first_name='Anneke' and last_name like '%sig' |
- +----------+------------+--------------------------------------------------------------------------------+
- 6 rows in set, 1 warning (0.00 sec)
当开启ICP时 查询在sending data环节时间消耗是 0.000189s
- mysql> show profile cpu,block io for query 1;
- +----------------------+----------+----------+------------+--------------+---------------+
- | Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
- +----------------------+----------+----------+------------+--------------+---------------+
- | starting | 0.000094 | 0.000000 | 0.000000 | 0 | 0 |
- | checking permissions | 0.000011 | 0.000000 | 0.000000 | 0 | 0 |
- | Opening tables | 0.000025 | 0.000000 | 0.000000 | 0 | 0 |
- | init | 0.000044 | 0.000000 | 0.000000 | 0 | 0 |
- | System lock | 0.000014 | 0.000000 | 0.000000 | 0 | 0 |
- | optimizing | 0.000021 | 0.000000 | 0.000000 | 0 | 0 |
- | statistics | 0.000093 | 0.000000 | 0.000000 | 0 | 0 |
- | preparing | 0.000024 | 0.000000 | 0.000000 | 0 | 0 |
- | executing | 0.000006 | 0.000000 | 0.000000 | 0 | 0 |
- | Sending data | 0.000189 | 0.000000 | 0.000000 | 0 | 0 |
- | end | 0.000019 | 0.000000 | 0.000000 | 0 | 0 |
- | query end | 0.000012 | 0.000000 | 0.000000 | 0 | 0 |
- | closing tables | 0.000013 | 0.000000 | 0.000000 | 0 | 0 |
- | freeing items | 0.000034 | 0.000000 | 0.000000 | 0 | 0 |
- | cleaning up | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
- +----------------------+----------+----------+------------+--------------+---------------+
- 15 rows in set, 1 warning (0.00 sec)
当关闭ICP时 查询在sending data环节时间消耗是 0.000735s
- mysql> show profile cpu,block io for query 2;
- +----------------------+----------+----------+------------+--------------+---------------+
- | Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
- +----------------------+----------+----------+------------+--------------+---------------+
- | starting | 0.000045 | 0.000000 | 0.000000 | 0 | 0 |
- | checking permissions | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
- | Opening tables | 0.000015 | 0.000000 | 0.000000 | 0 | 0 |
- | init | 0.000024 | 0.000000 | 0.000000 | 0 | 0 |
- | System lock | 0.000009 | 0.000000 | 0.000000 | 0 | 0 |
- | optimizing | 0.000012 | 0.000000 | 0.000000 | 0 | 0 |
- | statistics | 0.000049 | 0.000000 | 0.000000 | 0 | 0 |
- | preparing | 0.000016 | 0.000000 | 0.000000 | 0 | 0 |
- | executing | 0.000005 | 0.000000 | 0.000000 | 0 | 0 |
- | Sending data | 0.000735 | 0.001000 | 0.000000 | 0 | 0 |
- | end | 0.000008 | 0.000000 | 0.000000 | 0 | 0 |
- | query end | 0.000008 | 0.000000 | 0.000000 | 0 | 0 |
- | closing tables | 0.000009 | 0.000000 | 0.000000 | 0 | 0 |
- | freeing items | 0.000023 | 0.000000 | 0.000000 | 0 | 0 |
- | cleaning up | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
- +----------------------+----------+----------+------------+--------------+---------------+
- 15 rows in set, 1 warning (0.00 sec)
从上面的profile 可以看出ICP 开启时整个sql 执行时间是未开启的2/3,sending data 环节的时间消耗前者仅是后者的1/4。
- mysql> explain select * from employees where first_name='Anneke' and last_name like '%nta' ;
- +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-----------------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
- +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-----------------------+
- | 1 | SIMPLE | employees | ref | idx_emp_fnln | idx_emp_fnln | 44 | const | 224 | Using index condition |
- +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-----------------------+
- 1 row in set (0.00 sec)
ICP 关闭时的执行计划显示use where.
- mysql> explain select * from employees where first_name='Anneke' and last_name like '%nta' ;
- +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
- +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-------------+
- | 1 | SIMPLE | employees | ref | idx_emp_fnln | idx_emp_fnln | 44 | const | 224 | Using where |
- +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-------------+
- 1 row in set (0.00 sec)
案例分析
以上面的查询为例关闭ICP 时,存储引擎通前缀index first_name 访问表中225条first_name 为Anneke的数据,并在MySQL server层根据last_name like '%sig' 进行过滤
开启ICP 时,last_name 的like '%sig'条件可以通过索引字段last_name 进行过滤,在存储引擎内部通过与where条件的对比,直接过滤掉不符合条件的数据。该过程不回表,只访问符合条件的1条记录并返回给MySQL Server ,有效的减少了io访问和各层之间的交互。
ICP 关闭时 ,仅仅使用索引作为访问数据的方式。
ICP 开启时 ,MySQL将在存储引擎层 利用索引过滤数据,减少不必要的回表,注意 虚线的using where 表示如果where条件中含有没有被索引的字段,则还是要经过MySQL Server 层过滤。
四 ICP的使用限制
1 当sql需要全表访问时,ICP的优化策略可用于range, ref, eq_ref, ref_or_null 类型的访问数据方法 。
2 支持InnoDB和MyISAM表。
3 ICP只能用于二级索引,不能用于主索引。
4 并非全部where条件都可以用ICP筛选。
如果where条件的字段不在索引列中,还是要读取整表的记录到server端做where过滤。
5 ICP的加速效果取决于在存储引擎内通过ICP筛选掉的数据的比例。
6 5.6 版本的不支持分表的ICP 功能,5.7 版本的开始支持。
7 当sql 使用覆盖索引时,不支持ICP 优化方法。
- 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_emp_fnln | idx_emp_fnln | 94 | const,const | 1 | Using index condition |
- +----+-------------+-----------+------+---------------+--------------+---------+-------------+------+-----------------------+
- 1 row in set (0.00 sec)
- 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_emp_fnln | idx_emp_fnln | 94 | const,const | 1 | Using where; Using index |
- +----+-------------+-----------+------+---------------+--------------+---------+-------------+------+--------------------------+
- 1 row in set (0.00 sec)
0926MySQL中ICP索引下推的更多相关文章
- MySQL5.6之Index Condition Pushdown(ICP,索引条件下推)-Using index condition
http://blog.itpub.net/22664653/viewspace-1210844/ -- 这篇博客写的更细,以后看 ICP(index condition pushdown)是mysq ...
- 神奇的 SQL 之 ICP → 索引条件下推
开心一刻 楼主:来,我们先排练一遍 小伙伴们:好 嘿.哈.嚯 楼主:非常好,就是这个节奏,我们开始吧 楼主:啊.啊.啊,疼 ! 你们是不是故意的 ? 回表与覆盖索引 正式讲 ICP 之前了,我们先将相 ...
- Mysql系列(十二)—— 索引下推优化
索引条件下推(ICP)是对MySQL使用索引从表中检索行的情况的优化.如果没有ICP,存储引擎会遍历索引以查找基表中的行,并将它们返回给MySQL服务器,该服务器会评估WHERE行的条件.启用ICP后 ...
- MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)
本节内容: 1)索引基础 2)索引类型(Hash索引.有序数组.B+树) 3)索引的几个常见问题 1)联合索引 2)最左前缀原则 3)覆盖索引 4)索引下推 1. 索引基础 索引对查询的速度有着至关重 ...
- 五分钟搞懂MySQL索引下推
大家好,我是老三,今天分享一个小知识点--索引下推. 如果你在面试中,听到MySQL5.6"."索引优化" 之类的词语,你就要立马get到,这个问的是"索引下推 ...
- InnoDB 聚集索引和非聚集索引、覆盖索引、回表、索引下推简述
关于InnoDB 存储引擎的有聚集索引和非聚集索引,覆盖索引,回表,索引下推等概念,这些知识点比较多,也比较零碎,但是概念都是基于索引建立的,本文从索引查找数据讲述上述概念. 聚集索引和非聚集索引 在 ...
- MySQL索引下推,原来这么简单!
大家好,我是大彬~ 今天给大家分享MySQL的索引下推. 什么是索引下推 索引条件下推,也叫索引下推,英文全称Index Condition Pushdown,简称ICP. 索引下推是MySQL5.6 ...
- MySQL查询性能优化七种武器之索引下推
前面已经讲了MySQL的其他查询性能优化方式,没看过可以去了解一下: MySQL查询性能优化七种武器之索引潜水 MySQL查询性能优化七种武器之链路追踪 今天要讲的是MySQL的另一种查询性能优化方式 ...
- MySQL索引下推技术
索引下推整个思路如下: To see how this optimization works, consider first how an index scan proceeds when Index ...
随机推荐
- vim copy,find and replace
VIM选择文本块/复制/粘贴 在正常模式下(按ESC进入)按键v进入可视化模式,然后按键盘左右键或h,l键即可实现文本的选择.其它相关命令:v:按字符选择.经常使用的模式,所以亲自尝试一下它. V:按 ...
- ubuntu 关机命令
ubuntu 关机命令 关机命令 shutdown ubuntu的终端中默认的是当前用户的命令,只是普通用户,因此在终端器中可以使用sudo -sh 转换到管理员root用户下执行命令. 1)shut ...
- python lmdb demo 这接口和BDB一样恶心啊!
import lmdb lmdb_img_name = "test.lmdb" env = lmdb.open(lmdb_img_name, map_size=1e6) with ...
- Vue开发入门看这篇文章就够了
摘要: 很多值得了解的细节. 原文:Vue开发看这篇文章就够了 作者:Random Fundebug经授权转载,版权归原作者所有. 介绍 Vue 中文网 Vue github Vue.js 是一套构建 ...
- AE错误代码解释
每当我们在进行AE开发,出现错误时经常会出现错误代码,但是我们并不知道它到底代表什么意思,这里的而错误编码我们可以对照着找到我们需要的时候常详细信息(问题是,经常还是会出现没有错误编码HRESULT ...
- [转]rdlc报表中表达式的使用--switch和IIF范例
本文转自:http://hi.baidu.com/oypx1234/item/5b35dec4e03a3ad697445266 =Switch( Fields!MLWHLO.Value = " ...
- xx网络--工具集合
-- D:\workspace\bajie_projram\BJ.srfcb\BJ.srfcb\BJ.srfcb 8jielicai_New\App_Code\common\pg.cs---GetHt ...
- 2015 多校赛 第七场 1011 (hdu 5379)
题意:给定一棵树,树上有 n 个节点.问有多少种方案,使得在每个节点上依次放置数 1~n 后,每个节点的儿子节点上的数连续(比如 1 为根,有1-2,1-3,1-4,则令2,3,4上的数连续),每个子 ...
- RabbitMQ .NET消息队列使用入门(二)【多个队列间消息传输】
孤独将会是人生中遇见的最大困难. 实体类: DocumentType.cs public enum DocumentType { //日志 Journal = 1, //论文 Thesis = 2, ...
- PL/SQL之基础篇
参考文献:<Oracle完全学习手册>第11章 1.PL/SQL概述 PL/SQL(Procedure Language/Structuer Query Language)是Oracle对 ...