從LIKE、REGEXP實例看MySQL EXPLAIN及ICP

前言

衡量一個SQL語句的表現的方式,你們都知道使用EXPLAIN語句,字段想必你們也知道,可是經過實例我以爲仍是更好理解。本文不會對每一個字段進行過多地贅述,網上不少大神比我總結得好。本文基於LIKE與正則表達式的實例EXPLAIN的表現。html

  • 在分析SQL語句執行時,主要用到的列,分別爲typeExtra,下文的測試用例均爲官網提供的sakila數據庫,附上下載連接mysql

  • film表的狀況以下,其實只須要idx_title索引: 正則表達式

    Alt text

  • MySQL版本爲:8.0+sql

  • ps:能夠結合這篇文章看,這篇算做補充吧。數據庫

實例及分析

  • 場景:根據title來匹配相應的電影,從最簡單的=開始。
  • 注:做爲innodb引擎是一個衡量效率的指標,rows有可能不許確
  • filtered:The filtered column indicates an estimated percentage of table rows that will be filtered by the table condition.The maximum value is 100, which means no filtering of rows occurred. Values decreasing from 100 indicate increasing amounts of filtering. rows shows the estimated number of rows examined and rows × filtered shows the number of rows that will be joined with the following table. For example, if rows is 1000 and filtered is 50.00 (50%), the number of rows to be joined with the following table is 1000 × 50% = 500.

譯文:是一個多少行會被表條件過濾的百分比估計值,通常與rows列結合着看,filtered × rows就是被表條件過濾掉的行數。bash

=

explain select title from film where title= 'ACE GOLDFINGER';
複製代碼
  • 結果及分析:索引等於一個常量值,typeref,使用的keyidx_title,實際使用索引與'ACE GOLDFINGER'比較(即ref=CONST,因爲使用索引查找與常量匹配(讀取的行數rows1),因爲是使用覆蓋索引,沒有回表獲取數據行Extra就是Using index
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE film NULL ref idx_title idx_title 767 const 1 100.00 Using index
explain select * from film where title= 'ACE GOLDFINGER';
複製代碼
  • 結果及分析:惟一區別,因爲須要回表查詢其餘字段,就不是覆蓋索引了,Extra就是NULL
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE film NULL ref idx_title idx_title 767 const 1 100.00 NULL

LIKE

  • 你們都知道有前綴索引這一說,LIKE語句的關鍵之一就在於%位置,就分析下如下4種狀況。

%不在前面

explain select title from film where title LIKE 'A%';
複製代碼
  • 結果及分析:這裏須要注意的是typeExtra

一、type:這裏把LIKE當成了一個有限制的索引掃描, 不用遍歷全部索引,例如,索引BETWEEN 1 AND 100的效果。 二、讀取了46行數據 三、ExtraUsing where; Using index這兩個值同時在一塊兒,究竟是什麼意思呢?先賣個關子,後續詳細說~post

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE film NULL range idx_title idx_title 767 NULL 46 100.00 Using where; Using index
explain select * from film where title LIKE 'A%';
複製代碼
  • 結果及分析:又出現了一個新的ExtraUsing index condition,後面詳細說,其餘字段倒和前一個語句沒區別
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE film NULL range idx_title idx_title 767 NULL 46 100.00 Using index condition

%在前面

explain select title from film where title LIKE '%A';
複製代碼

結果及分析: 一、首先,不是有限的索引查找,而是使用索引查詢全表,因此typeindex。 二、讀取了1000行,過濾了1000 * 11.11的行數。性能

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE film NULL index null idx_title 767 NULL 1000 11.11 Using where; Using index
explain select * from film where title LIKE '%A';
複製代碼
  • 結果及分析: 一、沒有使用索引,全表掃描,按照條件過濾。 二、Using where:存儲引擎檢索行後,MySQL server再進行過濾後返回(出自高性能MySQL,附錄D EXPLAIN)。
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE film NULL ALL null null null NULL 1000 11.11 Using where

REGEXP

explain select title from film where title REGEXP '^A';
複製代碼
  • 結果及分析:正則表達式查詢使用了索引全表掃描,沒有被表條件過濾的行。
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE film NULL INDEX null idx_title 767 NULL 1000 100 Using where; Using index
explain select * from film where title REGEXP '^A';
複製代碼
  • 結果及分析:沒有使用到索引,全表掃描。
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE film NULL ALL null null null NULL 1000 100 Using where

Using where; Using indexUsing index condition

  • 這裏,我參考了官網,而後添加了本身的一些分析,歡迎你們糾錯。
  • Using where; Using index:簡單來說,咱們能夠分開來看,Using where就是MySQL Server在存儲引擎檢索行後,再過濾。Using index就是覆蓋索引查詢,不須要回表獲取行數據。加起來就是:使用覆蓋索引檢索行後,在MySQL Server進行過濾

Bonus:you may have something wrong in your query if the Extra value is not Using where and the table join type is ALL or index. 譯文:若是type爲ALL或index,可是Extra不是Using where時,查詢語句或許有問題。測試

  • Using index Condition:官方文檔說這個與Index Condition Pushdown Optimization有關,官網簡稱爲ICP,在InnoDB以及MyISAM均可以使用,這裏我截取InnoDB關鍵信息。

一、使用場景:the case where MySQL retrieves rows from a table using an index,索引檢索行時使用type爲ref、range、index時使用,僅用於range、ref、eq_ref、ref_or_null 二、背景:Without ICP, the storage engine traverses the index to locate rows in the base table and returns them to the MySQL server which evaluates the WHERE condition for the rows,沒有ICP,存儲引擎遍歷索引檢索出行,返回到MySQL Server層進行WHERE條件過濾(眼熟有沒有,using where)。 三、原理:With ICP enabled, and if parts of the WHERE condition can be evaluated by using only columns from the index, the MySQL server pushes this part of the WHERE condition down to the storage engine,若是WHERE條件或者其部分,僅使用索引中的列,MySQL server能夠將這部分的WHERE子句交給存儲引擎處理。(因爲交給存儲引擎,就是pushdown了 。。。) 四、做用:For InnoDB tables, ICP is used only for secondary indexes. The goal of ICP is to reduce the number of full-row reads and thereby reduce I/O operations. For InnoDB clustered indexes, the complete record is already read into the InnoDB buffer. Using ICP in this case does not reduce I/O,僅能夠在二級索引使用,減小回表獲取行數據次數,減小MySQL server與存儲引擎之間的I/O操做,聚簇索引因爲整條數據已經加載進InnoDB 緩衝區了,沒有減小I/O操做。優化

  • 其餘信息:

一、ICP is used for the range, ref, eq_ref, and ref_or_null access methods when there is a need to access full table rows,僅用於range、ref、eq_ref、ref_or_null的type,且須要回表獲取行數據的狀況。 二、其餘信息,請參考官網

  • 這就能夠解釋上述結果:

一、explain select * from film where title LIKE 'A%'; range且須要回表 二、explain select title from film where title LIKE 'A%';不須要回表,沒啓動ICP 三、explain select title from film where title LIKE '%A'; index,無法用ICP

  • 如何開啓關閉ICP

SET optimizer_switch = 'index_condition_pushdown=off'; SET optimizer_switch = 'index_condition_pushdown=on';

  • 關閉ICP後運行explain select * from film where title LIKE 'A%':
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE film NULL range idx_title idx_title 767 NULL 46 100.00 Using where

結論(在InnoDB中):ICP是一種MySQL針對二級索引在rangerefeq_refref_or_null數據訪問類型且不是覆蓋索引(Using index)的一個優化機制,將MySQL server中進行的行數據過濾(二級索引可處理的)下推(push down)到存儲引擎處理,減小回表讀取行數據的次數,減小MySQL server與存儲引擎之間的I/O操做。

小結

本文從實例運行EXPLAIN出發,簡單介紹了ICP,並對容易疏忽的LIKE以及正則表達式的結果進行了介紹。

後續,會盡可能保持援引官網或者書裏的資料,並結合實例分析,但願對你們有所幫助,也歡迎糾錯~

參考文章

相關文章
相關標籤/搜索