前言
这是 MySQL5.6 之后才出现的,是一种根据索引进行查询的优化方式,其运作原理是: 当有一个 SQL 语法用到索引的时候,在查找索引的过程中"顺便"过滤 where 条件,进而提升资料库的整体性能。
好吧,我相信只看上面这句话应该是很难理解。后面再举个例子来说明。
ICP
先举一个例子来说明
测试资料
有一个複合索引 (num, uname)
CREATE TABLE tb1 (id int not null auto_increment,num int,uname varchar(20),phone varchar(10),PRIMARY KEY(id),KEY(num, uname));INSERT INTO tb1(num, uname, phone) values(11,'Kobe Bryant','0912345678'),(12,'Michael jordan','0912876543'),(13,'Stephen curry','0912111111'),(14,'Lebron james ','0912222222'),(15,'James harden','0912333333');
◎查询
SELECT * FROM tb1 WHERE num = 14 and uname like '%james%'
*图1 *
从图1可以看到 Extra 栏位出现 : Using index condition。
表示优化器选择使用 ICP。
在没有ICP之前,这个 SELECT 只会用到 num 这个索引定位到 num = 14,将资料取出后再去过滤 uname 这个栏位。因为 uname like '%james%' 是无法使用索引的。
但是如果有启用 ICP,在定位到 num =14 的时后就直接进行 uname 的过滤,满足的话才取出资料。不过前提是 uname 也要在这个複合索引里面。
简单来说 ICP 就是查询时有一部分无法直接使用索引,这里就是指 uname 这个栏位。
※ 这里可能会有点疑问,有没有启用ICP 感觉差别在于一个是取出 num=14 后再去过滤,一个是定位到 num=14 就顺便过滤?差在哪?
这里我觉得有一个网站画的图蛮清楚的,分享过来给大家参考一下
★ 如果没有用ICP
--> 会到存储引擎层把符合索引(num=14) 的取出返回 server 层,在透过 where 去过滤
图2 参考至 一起学习Mysql索引三(ICP,索引条件下推)
★ 如果有启用ICP
--> 就可以利用複合索引中的 uname 这个栏位,当定位到 num=14 在看看是否满足 uname,满足的话就取出。也就是说 server 层把工作下推到存储引擎层
图3 参考至 一起学习Mysql索引三(ICP,索引条件下推)
小结
透过 ICP ,总之就是减少了 server 层的操作,因为下推到引擎层去处理了。
另外有一些限制
◎补充一个查询说明刚刚的有用到覆盖索引就不用ICP
SELECT id,num,uname FROM tb1 WHERE num = 14 and uname like '%james%'
这句因为 id,num,uname 在辅助索引中就可以取得,所以不须要回到丛集索引,
因为用了覆盖索引,所以不用ICP优化了。
资料库知识相当广泛,文中若有不正确的地方,也烦请各位大神不吝指教,谢谢
参考网站
一起学习Mysql索引三(ICP,索引条件下推)
MySQL原理与实践(一):一条select语句引出Server层和存储引擎层