MySQL 之 Index Condition Pushdown(ICP)

簡介

      Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一種在存儲引擎層使用索引過濾數據的一種優化方式。mysql

  • 當關閉ICP時,index 僅僅是data access 的一種訪問方式,存儲引擎經過索引從表獲取的數據會傳遞到MySQL Server 層進行where條件過濾。
  • 當打開ICP時,若是部分where條件能使用索引中的字段,MySQL Server 會把這部分下推到引擎層,能夠利用index過濾的where條件在存儲引擎層進行數據過濾,而非將全部經過index access的結果傳遞到MySQL server層進行where過濾.

     優化效果:ICP能減小引擎層訪問基表的次數和MySQL Server 訪問存儲引擎的次數,減小io次數,提升查詢語句性能。sql

ICP的使用限制

  • 當sql須要全表訪問時,ICP的優化策略可用於range, ref, eq_ref,  ref_or_null 類型的訪問數據方法 。
  • 支持InnoDB和MyISAM表。
  • ICP只能用於二級索引,不能用於主索引。
  • 並不是所有where條件均可以用ICP篩選。 若是where條件的字段不在索引列中,仍是要讀取整表的記錄到server端作where過濾。
  • ICP的加速效果取決於在存儲引擎內經過ICP篩選掉的數據的比例。
  • 5.6 版本的不支持分表的ICP 功能,5.7 版本的開始支持。
  • 當sql 使用覆蓋索引時,不支持ICP 優化方法。

實踐

mysql> show create table user\G
*************************** 1. row ***************************
Table: user
Create Table: CREATE TABLE `user` (
     `id` int(11) NOT NULL AUTO_INCREMENT,
     `username` varchar(50) NOT NULL,
     `password` varchar(50) NOT NULL,
     `score` smallint(3) NOT NULL,
     `mobile` char(11) NOT NULL DEFAULT '',
      PRIMARY KEY (`id`),
      KEY `unique_username` (`username`),
      KEY `pre_idx` (`score`,`mobile`,`username`)
) ENGINE=InnoDB AUTO_INCREMENT=200003 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)服務器

開啓ICP

        mysql> set optimizer_switch="index_condition_pushdown=on";性能

mysql> explain select * from user where score=60 and mobile like '%75%' and username like '%username11%'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: user
partitions: NULL
type: ref
possible_keys: pre_idx
key: pre_idx
key_len: 2
ref: const
rows: 2012
filtered: 1.23
Extra: Using index condition
1 row in set, 1 warning (0.00 sec)優化

從explain 着灰底色的參數能夠看到,使用了複合索引 pre_idx,而且只使用了 score字段的索引(由於mobile  與 username 使用了模糊查詢,沒法使用索引),但Extra列並無Using where,而是Using index condition,說明使用了ICP,在存儲引擎使用了索引過濾where條件,再也不把經過索引查找到的數據傳輸到mysql服務器層經過where條件過濾。
spa

 關閉ICP

        mysql> set optimizer_switch="index_condition_pushdown=off";server

mysql> explain select * from user where score=60 and mobile like '%75%' and username like '%username11%'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: user
partitions: NULL
type: ref
possible_keys: pre_idx
key: pre_idx
key_len: 2
ref: const
rows: 2012
filtered: 1.23
Extra: Using where
1 row in set, 1 warning (0.00 sec)blog

 從explain 着灰底色的參數能夠看到,使用了複合索引 pre_idx,而且只使用了 score字段的索引(由於mobile  與 username 使用了模糊查詢,沒法使用索引),Extra出現Using where。索引

 

從案例能夠看到,當開啓ICP時 查詢在sending data環節時間消耗是 0.006537s,未開啓時是0.329598s,如今該表的數據量爲20w,差別已經很是明顯了。it

相關文章
相關標籤/搜索