MySQL 优化之 ICP (index condition pushdown:索引条件下推)
ICP技术是在MySQL5.6中引入的一种索引优化技术。它能减少在使用 二级索引 过滤where条件时的回表次数 和 减少MySQL server层和引擎层的交互次数。在索引组织表中,使用二级索引进行回表的代价相比堆表中是要高一些的。相关文档地址:http://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html
Index Condition Pushdown optimization is used for the range, ref, eq_ref, and ref_or_null access methods when there is a need to access full table rows. This strategy can be used for InnoDB and MyISAM tables. (Note that index condition pushdown is not supported with partitioned tables in MySQL 5.6; this issue is resolved in MySQL 5.7.) For InnoDB tables, however, ICP is used only for secondary indexes. The goal of ICP is to reduce the number of full-record reads and thereby reduce IO operations. For InnoDB clustered indexes(值主键索引), the complete record is already read into the InnoDB buffer. Using ICP in this case does not reduce IO.
要想深入理解 ICP 技术,必须先理解数据库是如何处理 where 中的条件的。具体可以参考何登成博士的文章:http://hedengcheng.com/?p=577
对 where 中过滤条件的处理,根据索引使用情况分成了三种:index key, index filter, table filter
1. index key
用于确定SQL查询在索引中的连续范围(起始范围+结束范围)的查询条件,被称之为Index Key。由于一个范围,至少包含一个起始与一个终止,因此Index Key也被拆分为Index First Key和Index Last Key,分别用于定位索引查找的起始,以及索引查询的终止条件。也就是说根据索引来确定扫描的范围。
2. index filter
在使用 index key 确定了起始范围和介绍范围之后,在此范围之内,还有一些记录不符合where 条件,如果这些条件可以使用索引进行过滤,那么就是 index filter。也就是说用索引来进行where条件过滤。
3. table filter
where 中的条件不能使用索引进行处理的,只能访问table,进行条件过滤了。
也就是说各种各样的 where 条件,在进行处理时,分成了上面三种情况,一种条件会使用索引确定扫描的范围;一种条件可以在索引中进行过滤;一种必须回表进行过滤;
如何确定哪些where条件分别是 index key, index filter, table filter,可以参考何博士的文章。
在 MySQL5.6 之前,并不区分Index Filter与Table Filter,统统将Index First Key与Index Last Key范围内的索引记录,回表读取完整记录,然后返回给MySQL Server层进行过滤。而在MySQL 5.6之后,Index Filter与Table Filter分离,Index Filter下降到InnoDB的索引层面进行过滤,减少了回表与返回MySQL Server层的记录交互开销,提高了SQL的执行效率。
所以所谓的 ICP 技术,其实就是 index filter 技术而已。只不过因为MySQL的架构原因,分成了server层和引擎层,才有所谓的“下推”的说法。所以ICP其实就是实现了index filter技术,将原来的在server层进行的table filter中可以进行index filter的部分,在引擎层面使用index filter进行处理,不再需要回表进行table filter。
4. ICP 技术启用前后比较
To see how this optimization works, consider first how an index scan proceeds when Index Condition Pushdown is not used:
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.
Test the part of the
WHEREcondition that applies to this table. Accept or reject the row based on the test result.
When Index Condition Pushdown is used, the scan proceeds like this instead:
Get the next row's index tuple (but not the full table row).
Test the part of the
WHEREcondition 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.If the condition is satisfied, use the index tuple to locate and read the full table row.
Test the remaining part of the
WHEREcondition that applies to this table. Accept or reject the row based on the test result.
When Index Condition Pushdown is used, the Extra column in EXPLAIN output shows Using index condition. It will not show Index only because that does not apply when full table rows must be read.
5. ICP 例子
官方文档给出了一个例子:
Suppose that we have a table containing information about people and their addresses and that the table has an index defined as INDEX (zipcode, lastname, firstname). If we know a person's zipcode value but are not sure about the last name, we can search like this:
SELECT * FROM people WHERE zipcode='' AND lastname LIKE '%etrunia%' AND address LIKE '%Main Street%';
MySQL can use the index to scan through people with zipcode='95054'. The second part (lastname LIKE '%etrunia%') cannot be used to limit the number of rows that must be scanned, so without Index Condition Pushdown, this query must retrieve full table rows for all the people who have zipcode='95054'.
With Index Condition Pushdown, MySQL will check the lastname LIKE '%etrunia%' part before reading the full table row. This avoids reading full rows corresponding to all index tuples that do not match the lastname condition.
Index Condition Pushdown is enabled by default; it can be controlled with the optimizer_switch system variable by setting the index_condition_pushdown flag. See Section 8.9.2, “Controlling Switchable Optimizations”.
上面例子中的 lastername like '%etrunia%' 和 address like '%Main Street%' 本来是无法使用复合索引 index(zipcode, lastername, firstname) 进行过滤的,但是因为有了ICP技术,所以他们可以在 index filter 阶段使用索引进行过滤,无需回表进行 table filter.
例子2:
role_goods 表上有组合索引 index(roleId,status,number),下面的select语句,因为 “索引最左前缀原则”,只能使用到 组合索引的 roleId 部分,但是因为 ICP 技术的存在,现在 number 条件过滤也可以在 index filter 阶段完成了,无需像以前一样需要进行 table filer 了:
mysql> explain select * from role_goods where roleId=100000001 and number=1;
+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+
| 1 | SIMPLE | role_goods | ref | roleId_2 | roleId_2 | 9 | const | 14 | Using index condition |
+----+-------------+------------+------+---------------+----------+---------+-------+------+-----------------------+
1 row in set (0.01 sec)
可以看到 key_len = 9, 因为 roleId 是big int 类型,所以 key_len = 8 + 1 = 9; 所以在 index key 阶段中,并没有使用到 组合索引 index(roleId,status,number) 中的 number 字段(因为中间有一个status字段没有出现在where 条件中),但是 “Using index condition” 却说明使用到了ICP技术,显然是 number =1 条件过滤使用到了ICP技术。
参考:
http://hedengcheng.com/?p=577
http://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html
MySQL 优化之 ICP (index condition pushdown:索引条件下推)的更多相关文章
- mysql -- 优化之ICP(index condition pushdown)
一.为了方法说明ICP是什么.假设有如下的表和查询: create table person( id int unsigned auto_increment primary key, home_add ...
- 浅析MySQL中的Index Condition Pushdown (ICP 索引条件下推)和Multi-Range Read(MRR 索引多范围查找)查询优化
本文出处:http://www.cnblogs.com/wy123/p/7374078.html(保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误 ...
- MySQL 中Index Condition Pushdown (ICP 索引条件下推)和Multi-Range Read(MRR 索引多范围查找)查询优化
一.ICP优化原理 Index Condition Pushdown (ICP),也称为索引条件下推,体现在执行计划的上是会出现Using index condition(Extra列,当然Extra ...
- 1229【MySQL】性能优化之 Index Condition Pushdown
转自http://blog.itpub.net/22664653/viewspace-1210844/ [MySQL]性能优化之 Index Condition Pushdown2014-07-06 ...
- MySQL索引与Index Condition Pushdown
实际上,这个页面所讲述的是在MariaDB 5.3.3(MySQL是在5.6)开始引入的一种叫做Index Condition Pushdown(以下简称ICP)的查询优化方式.由于本身不是一个层面的 ...
- MySQL ICP(Index Condition Pushdown)特性
一.SQL的where条件提取规则 在ICP(Index Condition Pushdown,索引条件下推)特性之前,必须先搞明白根据何登成大神总结出一套放置于所有SQL语句而皆准的where查询条 ...
- MySQL 之 Index Condition Pushdown(ICP)
简介 Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式. 当关闭ICP时,index 仅仅是data ...
- MySQL5.6之Index Condition Pushdown(ICP,索引条件下推)-Using index condition
http://blog.itpub.net/22664653/viewspace-1210844/ -- 这篇博客写的更细,以后看 ICP(index condition pushdown)是mysq ...
- MySQL索引与Index Condition Pushdown(二)
实验 先从一个简单的实验开始直观认识ICP的作用. 安装数据库 首先需要安装一个支持ICP的MariaDB或MySQL数据库.我使用的是MariaDB 5.5.34,如果是使用MySQL则需要5.6版 ...
随机推荐
- ExtJS 4.2 业务开发(二)数据展示和查询
本篇开始模拟一个船舶管理系统,提供查询.添加.修改船舶的功能,这里介绍其中的数据展示和查询功能. 目录 1. 数据展示 2. 数据查询 3. 在线演示 1. 数据展示 在这里我们将模拟一个船舶管理系统 ...
- CoreCRM 开发实录——Travis-CI 实现 .NET Core 程度在 macOS 上的构建和测试 [无水干货]
上一篇文章我提到:为了使用"国货",我把 Linux 上的构建和测试委托给了 DaoCloud,而 Travis-CI 不能放着不用啊.还好,这货支持 macOS 系统.所以就把 ...
- 设置tomcat远程debug
查看端口占用情况命令: netstat -tunlp |grep 8000 tomcat 启动远程debug: startup.sh 中的最后一行 exec "$PRGDIR"/& ...
- ASP.NET Core 中文文档 第四章 MVC(3.9)视图组件
作者: Rick Anderson 翻译: 娄宇(Lyrics) 校对: 高嵩 章节: 介绍视图组件 创建视图组件 调用视图组件 演练:创建一个简单的视图组件 附加的资源 查看或下载示例代码 介绍视图 ...
- Canvas讲解
1.Canvas是什么? 简单地说canvas是画布,可以进行画任何的线.图形.填充等一系列的操作,而且操作的画图就是js, 提供简单的二维矢量绘图. 2.步骤: <canvas id=&quo ...
- Android—Service与Activity的交互
service-Android的四大组件之一.人称"后台服务"指其本身的运行并不依赖于用户可视的UI界面 实际开发中我们经常需要service和activity之间可以相互传递数据 ...
- TFS 2015 敏捷开发实践 – 看板的使用
看板在现代应用开发过程中使用非常广泛,不管是使用传统的瀑布式开发还是敏捷开发,都可以使用看板管理.因为看板拥有简单的管理方法,直观的显示方式,所以很多软件开发团队选择使用看板进行软件开发管理.本文不在 ...
- HTML5 程序设计 - 使用HTML5 Canvas API
请你跟着本篇示例代码实现每个示例,30分钟后,你会高喊:“HTML5 Canvas?!在哥面前,那都不是事儿!” 呵呵.不要被滚动条吓到,很多都是代码和图片.我没有分开写,不过上面给大家提供了目录,方 ...
- HTML 学习笔记 JQuery(DOM 操作2)
接着上一节的将,这一节从复制节点讲起 复制节点 继续使用之前的例子 如果单击<li>元素后 需要在复制一个<li>元素,可以使用clone()方法完成.全部代码如下 <h ...
- video.js--很赞的H5视频播放库
video.js是一款很流行的html5视频播放插件.很适合在移动端播放视频(比如微信网页),功能强大,且支持降级到flash,兼容ie8.官网:http://videojs.com/ git& ...