在MySQL中,咱們能夠經過EXPLAIN命令獲取MySQL如何執行SELECT語句的信息,包括在SELECT語句執行過程當中表如何鏈接和鏈接的順序。微信
下面分別對EXPLAIN命令結果的每一列進行說明:post
select_type:表示SELECT的類型,常見的取值有:性能
類型 | 說明 |
---|---|
SIMPLE | 簡單表,不使用錶鏈接或子查詢 |
PRIMARY | 主查詢,即外層的查詢 |
UNION | UNION中的第二個或者後面的查詢語句 |
SUBQUERY | 子查詢中的第一個 |
table:輸出結果集的表(表別名)學習
type:表示MySQL在表中找到所需行的方式,或者叫訪問類型。常見訪問類型以下,從上到下,性能由差到最好:優化
ALL | 全表掃描 |
---|---|
index | 索引全掃描 |
range | 索引範圍掃描 |
ref | 非惟一索引掃描 |
eq_ref | 惟一索引掃描 |
const,system | 單表最多有一個匹配行 |
NULL | 不用掃描表或索引 |
type=ALL,全表掃描,MySQL遍歷全表來找到匹配行spa
通常是沒有where條件或者where條件沒有使用索引的查詢語句code
EXPLAIN SELECT * FROM customer WHERE active=0;
server
type=index,索引全掃描,MySQL遍歷整個索引來查詢匹配行,並不會掃描表blog
通常是查詢的字段都有索引的查詢語句排序
EXPLAIN SELECT store_id FROM customer;
type=range,索引範圍掃描,經常使用於<、<=、>、>=、between等操做
EXPLAIN SELECT * FROM customer WHERE customer_id>=10 AND customer_id<=20;
注意這種狀況下比較的字段是須要加索引的,若是沒有索引,則MySQL會進行全表掃描,以下面這種狀況,create_date字段沒有加索引:
EXPLAIN SELECT * FROM customer WHERE create_date>='2006-02-13' ;
type=ref,使用非惟一索引或惟一索引的前綴掃描,返回匹配某個單獨值的記錄行
store_id
字段存在普通索引(非惟一索引)
EXPLAIN SELECT * FROM customer WHERE store_id=10;
ref類型還常常會出如今join操做中:
customer、payment表關聯查詢,關聯字段customer.customer_id
(主鍵),payment.customer_id
(非惟一索引)。表關聯查詢時一定會有一張表進行全表掃描,此表必定是幾張表中記錄行數最少的表,而後再經過非惟一索引尋找其餘關聯表中的匹配行,以此達到表關聯時掃描行數最少。
由於customer、payment兩表中customer表的記錄行數最少,因此customer表進行全表掃描,payment表經過非惟一索引尋找匹配行。
EXPLAIN SELECT * FROM customer customer INNER JOIN payment payment ON customer.customer_id = payment.customer_id;
type=eq_ref,相似ref,區別在於使用的索引是惟一索引,對於每一個索引鍵值,表中只有一條記錄匹配
eq_ref通常出如今多表鏈接時使用primary key或者unique index做爲關聯條件。
film、film_text表關聯查詢和上一條所說的基本一致,只不過關聯條件由非惟一索引變成了主鍵。
EXPLAIN SELECT * FROM film film INNER JOIN film_text film_text ON film.film_id = film_text.film_id;
type=const/system,單表中最多有一條匹配行,查詢起來很是迅速,因此這個匹配行的其餘列的值能夠被優化器在當前查詢中看成常量來處理
const/system出如今根據主鍵primary key或者 惟一索引 unique index 進行的查詢
根據主鍵primary key進行的查詢:
EXPLAIN SELECT * FROM customer WHERE customer_id =10;
根據惟一索引unique index進行的查詢:
EXPLAIN SELECT * FROM customer WHERE email ='MARY.SMITH@sakilacustomer.org';
type=NULL,MySQL不用訪問表或者索引,直接就可以獲得結果
possible_keys: 表示查詢可能使用的索引
key: 實際使用的索引
key_len: 使用索引字段的長度
ref: 使用哪一個列或常數與key一塊兒從表中選擇行。
rows: 掃描行的數量
filtered: 存儲引擎返回的數據在server層過濾後,剩下多少知足查詢的記錄數量的比例(百分比)
Extra: 執行狀況的說明和描述,包含不適合在其餘列中顯示可是對執行計劃很是重要的額外信息
最主要的有一下三種:
Using Index | 表示索引覆蓋,不會回表查詢 |
---|---|
Using Where | 表示進行了回表查詢 |
Using Index Condition | 表示進行了ICP優化 |
Using Flesort | 表示MySQL需額外排序操做, 不能經過索引順序達到排序效果 |
MySQL5.6引入了Index Condition Pushdown(ICP)的特性,進一步優化了查詢。Pushdown表示操做下放,某些狀況下的條件過濾操做下放到存儲引擎。
EXPLAIN SELECT * FROM rental WHERE rental_date='2005-05-25' AND customer_id>=300 AND customer_id<=400;
在5.6版本以前:
優化器首先使用複合索引idx_rental_date過濾出符合條件rental_date='2005-05-25'
的記錄,而後根據複合索引idx_rental_date回表獲取記錄,最終根據條件customer_id>=300 AND customer_id<=400
過濾出最後的查詢結果(在服務層完成)。
在5.6版本以後:
MySQL使用了ICP來進一步優化查詢,在檢索的時候,把條件customer_id>=300 AND customer_id<=400
也推到存儲引擎層完成過濾,這樣可以下降沒必要要的IO訪問。Extra爲Using index condition
就表示使用了ICP優化。
《深刻淺出MySQL》