Mysql应用MySQL Index Condition Pushdown(ICP)性能优化方法实例
《Mysql应用MySQL Index Condition Pushdown(ICP)性能优化方法实例》要点: 一 观点介绍MYSQL入门 Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特征,是一种在存储引擎层使用索引过滤数据的一种优化方式.MYSQL入门 a 当关闭ICP时,index 仅仅是data access 的一种拜访方式,存储引擎通过索引回表获取的数据会传递到MySQL Server 层进行where条件过滤.MYSQL入门 b 当打开ICP时,如果部门where条件能使用索引中的字段,MySQL Server 会把这部门下推到引擎层,可以利用index过滤的where条件在存储引擎层进行数据过滤,而非将所有通过index access的结果传递到MySQL server层进行where过滤.MYSQL入门 优化效果:ICP能减少引擎层拜访基表的次数和MySQL Server 拜访存储引擎的次数,减少io次数,提高查询语句性能.MYSQL入门 二 原理MYSQL入门 Index Condition Pushdown is not used:MYSQL入门 ? 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. 三 理论案例MYSQL入门 a 环境准备 ???? 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 模糊查询,不克不及使用索引. mysql> set optimizer_switch='index_condition_pushdown=off'; Query OK,0 rows affected (0.00 sec) mysql> SET profiling = 1; Query OK,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,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) 案例阐发MYSQL入门 以上面的查询为例关闭ICP 时,存储引擎通前缀index first_name 拜访表中225条first_name 为Anneke的数据,并在MySQL server层根据last_name like '%sig' 进行过滤 ICP 关闭时,仅仅使用索引作为拜访数据的方式.MYSQL入门 ICP 开启时,MySQL将在存储引擎层 利用索引过滤数据,减少不需要的回表,注意 虚线的using where 表示如果where条件中含有没有被索引的字段,则还是要经过MySQL Server 层过滤.MYSQL入门 四 ICP的使用限定 MYSQL入门 1 当sql需要全表拜访时,ICP的优化策略可用于range,ref,eq_ref,? ref_or_null 类型的拜访数据方法 . 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) 欢迎参与《Mysql应用MySQL Index Condition Pushdown(ICP)性能优化方法实例》讨论,分享您的想法,编程之家PHP学院为您提供专业教程。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |