索引下推(Index Condition Pushdown) ICP 是 Mysql5.6 之后新增的性能,次要的外围点就在于把数据筛选的过程放在了存储引擎层去解决,而不是像之前一样放到 Server 层去做过滤。
尽管这是一个比较简单的概念,然而可能很多不仔细的同学对于索引下推会存在一个小小的误区,至于是什么,请看下文。
什么是索引下推
首先,咱们创立一张 user
表,同时建设 age_name
的联结索引,同时插入 3 条测试数据。
而后,咱们执行查问 explain SELECT * from user where age >10 and name = 'a'
,如下图所示,就会看见Extra
中显示了 Using index condition
,你可能就晓得了,这示意呈现了 索引下推 了。
没错,针对这个查问场景就是索引下推,那到底什么是索引下推呢?
依照咱们上述的场景,实际上就存在两个索引树,一个是主键索引,存储了具体的数据的信息,另外则是 age_name
的联结索引,保留了主键的 ID。
在没有 ICP 索引下推的时候,这个查问的流程应该是这样(略过无关的细节):
- Mysql Server 层调用 API 查问存储引擎数据
- 存储引擎依据联结索引首先通过条件找到所有 age>10 的数据
- 找到的每一条数据都依据主键索引进行回表查问,直到找到不符合条件的后果
- 返回数据给 Server 层,Server 依据条件对后果进行过滤,流程完结
而有了 ICP 之后的流程则是这样:
- Mysql Server 层调用 API 查问存储引擎数据
- 存储引擎依据联结索引首先通过条件找到所有 age>10 的数据,依据联结索引中曾经存在的
name
数据进行过滤,找到符合条件的数据 - 依据找到符合条件的数据,回表查问
- 返回数据给 Server 层,流程完结
比照这两个流程就会很显著的发现,应用 ICP 之后咱们就是简略的通过联结索引中原本就有的数据间接过滤了,不须要再查到一堆无用的数据去 Server 层进行过滤,这样的话缩小了回表的次数和返回的数据,IO 次数缩小了,对性能有很好的晋升。
依照官网文档所说,ICP 其实也存在肯定的应用限度场景,只说要害的,乌七八糟的不说。
- 首先,ICP 实用于 range、ref、eq_ref 和 ref_or_null 的场景下
- InnoDB 和 MyISAM 都反对 ICP,Mysql partition 分表的话也能够应用
- 对于 InndoDB 而言,ICP 只反对二级索引,因为主键索引它用不上不是吗?
- 子查问不反对
当初咱们根本都应用的 5.6 以上的版本了,默认就是开启 ICP 的,想敞开的话能够通过命令SET optimizer_switch = 'index_condition_pushdown=off';
。
一个小小的误区
一般来说,失常状况下 Mysql 一次查问都只能走一个索引,咱们来批改上述的表构造,把联结索引改为两个独自的索引,数据放弃不变
而后咱们执行查问explain SELECT * from user where age >10 and name like 'a%'
,后果如下图。
你会发现,我靠,怎么还有索引下推?这不迷信对不对,如同无法解释嘛,难道这一次索引下推还能先查出 age
再下推到 name
索引吗,这齐全不合理啊。
其实不然,实在的状况是,Using index condition
并不代表肯定是应用了索引下推,只是代表能够应用,然而不肯定用了。。。
这个就有点坑爹,可能会对咱们判断的时候造成误会啊。
如果你去网上搜很多人举例子这样建索引,而后通知你这就是索引下推的时候,你能够纵情的喷他了,咱们说索引下推肯定是在联结索引的状况下,依据联结索引自身就有的数据间接做一次过滤,而不必再进行屡次无用的回表再到 Server 层进行过滤,这一点你要很明确才行。
好了,明天的话题就到这里完结,我是艾小仙,咱们下期见。
(原本我想多画两张图的,不过如同感觉这个概念切实太简略了,画的花里胡哨的反而没有意义,就像你说笼罩索引、回表还画好几张图给你解释吗,没有必要对不对,必定不是因为我懒。。。)