索引下推
官網地址:Index Condition Pushdown Optimization
個人理解:
開啟ICP後,在查詢索引時,會先檢查無效索引(未走上的索引)是否滿足條件,減少回表查詢的次數,從而節省了查詢 滿足有效索引列條件下的 不符合無效索引列條件的所有行的查詢時間。
很明顯,索引沒有走到
uname
列- 在關閉ICP時,MySQL會回表查詢`uname`!='5f686d59875ef'這個條件的完整行
- 在開啟ICP時,MySQL會先檢查索引中的`uname`,然後在進行全表查詢
實際查詢,對比開啟和關閉ICP時所用時間
SET profiling = 1; -- 開啟profiling
SET query_cache_type = 0; -- 關閉query_cache
SET GLOBAL query_cache_size = 0;
SET optimizer_switch = 'index_condition_pushdown=off'; -- 關閉ICP
SET optimizer_switch = 'index_condition_pushdown=on'; -- 開啟ICP
- 先看看EXPLAIN,有效索引列:`dept_id`,無效索引列:`uname`
- 再在開啟關閉的情況下,分別執行三次SQL,檢視查詢時間;開啟後比關閉後節省了大概75%的時間
ICP注意事項:
- EXPLAIN中的type須是range, ref, eq_ref, ref_or_null之一
- 支援引擎:Myisam,InnoDB,允許分割槽
- 對於InnoDB,不支援聚簇索引,只支援二級索引
- 不支援虛擬列,子查詢,儲存函式,觸發條件
- 索引覆蓋時,不用ICP
- ORDER BY子句中的索引列為DESC
- GROUP BY子句中不含有非索引列
EXPLAIN中的type是range:
- EXPLAIN中,type為range時,MySQL會根據符合有效索引列條件的計算rows(InnoDB是估值),如果過大,即使用索引不划算,將不走索引,從而不使用ICP
索引覆蓋
SELECT子句中查詢的欄位只有索引列,因此不需要根據二級索引查到的聚簇索引,再次回表查詢完整行。
由於ORDER BY子句,使用ICP的情況
- 只有當WHERE子句中的索引列以及OREDR BY子句中的索引列符合最左原則,且ORDER BY子句中的索引列為ASC時,才不會額外使用檔案排序
- 上述條件中的ORDER BY子句中的索引列為DESC時,將不使用ICP
由於GROUP BY子句,使用ICP的情況
- 當WHERE子句中滿足最左原則,GROUP BY子句中不含有非索引列
本作品採用《CC 協議》,轉載必須註明作者和本文連結