原文
https://mp.weixin.qq.com/s/-BlLvBKcF-yalELY7XkqaQ
1、執行計劃是什麼?
執行計劃,簡單的來說,是SQL在數據庫中執行時的表現情況,通常用於SQL性能分析,優化等場景。在MySQL中使用 explain 關鍵字來查看。如下所示:
1.查詢t_base_user
select * from t_base_user where name="andyqian";
2.查看上述語句的執行計劃
explain select * from t_base_user where name="andyqian";
執行查看上述2語句後,我們可以得出以下執行計劃
上面這個執行計劃給到的信息是: 這是一個簡單的SQL,全表掃描,共掃描1行,Using where條件在t_base_user表中篩選出記錄。發現該語句並沒有走索引,爲什麼是這樣的呢?別急,我們緊接着看下一節。上面執行計劃是什麼意思呢?有什麼參考價值呢?
2、讀懂執行計劃
通過上面,我們知道了什麼是執行計劃,也看到了執行計劃到底是什麼東西,現在我們來具體瞭解一下,MySQL執行計劃中,每個屬性代表的是什麼意思?
我們一一來介紹,並說明每個屬性有哪些可選值,以及每個可選值的意思。
名字 | 用途 | 詳細解釋 |
---|---|---|
id | 表格查詢的順序編號。 | 降序查看,id相同的從上到下查查看。id可以爲null ,當table爲( union ,m,n )類型的時候,id爲null,這個時候,id的順序爲 m跟n的後面。 |
select_type | 查詢的方式 | 下文詳細說明。 |
table | 表格名稱 | 表示輸出行數據所在表 |
partitions | 分區名稱 | 查詢使用到表分區的分區名。 |
type | 表連接的類型 | 下文詳細說明。 |
possible_keys | 可能使用到的索引 | 這裏的索引只是可能會有到,實際不一定會用到。 |
key | 使用到的索引 | 實際使用的索引。 |
key_len | 使用到索引的長度 | 比如多列索引,只用到最左的一列,那麼使用到索引的長度則爲該列的長度,故該值不一定等於 key 列索引的長度。 |
ref | 謂詞的關聯信息 | 當 join type 爲 const、eq_ref 或者 ref 時,謂詞的關聯信息。可能爲 :null(非 const \ eq_ref \ ref join type 時)、const(常量)、關聯的謂詞列名。 |
rows | 掃描的行數 | 該表格掃描到的行數。這裏注意在mysql裏邊是嵌套鏈接,所以,需要把所有rows相乘就會得到查詢數據行關聯的次數 |
filtered | 實際顯示行數佔掃描rows的比例 | 實際顯示的行數 = rows * filtered / 100 |
extra | 特性使用 |
2.1 、SELECT_TYPE
- SIMPLE,簡單查詢方式,不使用UNION跟子查詢;
- PRIMARY,該表格位於最外層開始查詢,通常會跟其他查詢方式組合;
- UNION,UNION 第一個SELECT 爲PRIMARY,第二個及之後的所有SELECT 爲 UNION SELECT TYPE;
- UNION RESULT,每個結果集的取出來後,會做合併操作,這個操作就是 UNION RESULT;
- DEPENDENT UNION,子查詢中的UNION操作,從UNION 第二個及之後的所有SELECT語句的SELECT TYPE爲DEPENDENT UNION,這個一般跟DEPENDENT SUBQUERY一起結合應用,子查詢中UNION的第一個爲DEPENDENT SUBQUERY;
- DEPENDENT SUBQUERY,子查詢中內層的第一個SELECT,依賴於外部查詢的結果集;
- SUBQUERY,子查詢內層查詢的第一個SELECT,結果不依賴於外部查詢結果集(不會被數據庫引擎改寫的情況);
- DERIVED,查詢使用內聯視圖;
- MATERIALIZED,子查詢物化,表出現在非相關子查詢中 並且需要進行物化時會出現MATERIALIZED關鍵詞;
- UNCACHEABLE SUBQUERY,結果集無法緩存的子查詢,需要逐次查詢;
- UNCACHEABLE UNION,表示子查詢不可被物化 需要逐次運行。
2.2 type
性能排序:null->system->const->eq-ref->ref->fulltext->ref_or_null->index_merge->unique_subquery->index_subquery->range->index->ALL
- null,不訪問任何一個表格
- system
官網解釋:The table has only one row (= system table). This is a special case of the const join type.
join type 爲const,並且表格僅含有1行記錄。 - const
主鍵或者唯一索引的常量查詢,表格最多隻有1行記錄符合查詢,通常const使用到主鍵或者唯一索引進行定值查詢。
常量查詢非常快。
- eq_ref
join 查詢過程中,關聯條件爲主鍵或者唯一索引,出來的行數不止一行
eq_ref是一種性能非常好的 join 操作。
例子說明:首先從su表格查詢所有數據共7行出來,然後每一行跟 xin 的主鍵id中的1行做匹配。
- ref
非聚集索引的常量查詢
性能也是很不錯的。
- fulltext
查詢的過程中,使用到了 fulltext 索引(fulltext index在innodb引擎中,只有5.6版本之後的支持)
例子是innodb引擎下、帶fulltext index的表格查詢
- ref_or_null
跟ref查詢類似,在ref的查詢基礎上,不過會加多一個null值的條件查詢
- index merg
當條件謂詞使用到多個索引的最左邊列並且謂詞之間的連接爲or的情況下,會使用到 索引聯合查詢
- unique subquery
eq_ref的一個分支,查詢主鍵的子查詢:
value IN (SELECT primary_key FROM single_table WHERE some_expr) - index subquery
ref的一個分支,查詢非聚集索引的子查詢:
value IN (SELECT key_column FROM single_table WHERE some_expr) - range
當謂詞使用到索引範圍查詢的時候:=、<>、>、>=、<、<=、IS NULL、BETWEEN、IN、<=> (這是個表達式:左邊可以推出右邊,右邊也可推出左邊)
- index
使用到索引,但是不是索引查找,而是對索引樹做一個掃描,即使是索引掃描,大多數情況下也是比全表掃描性能要好的,因爲索引樹上的鍵值只有索引列鍵值+主鍵,而全表掃描則是在 聚集索引樹(主鍵+所有列)上進行掃描,索引樹相比之下要廋得多跟小得多了。
- all
全表掃描,性能比較差。
關於 index跟all,這裏再舉一個例子說明下
下圖中,表格su有3個索引:主鍵、ix_age、ix_name,這三個索引樹的內容分別爲:主鍵id+所有列、age+主鍵id、name+主鍵id,依次,當掃描主鍵id查詢的時候,這三個索引都能夠提供 主鍵id列,那麼哪個性能比較好呢?索引樹最小的,掃描次數最少的則爲最優,根據索引數內容可得大小:ix_age < ix_name < pk,故執行計劃會選擇 ix_age。
2.3 ref
當 join type 爲 eq_ref 或者 ref 時,謂詞的關聯信息。可能爲 :null(非 eq_ref\ref join type時)、const(常量)、關聯的謂詞列名。
2.4 extra
常用到
Using index,使用到索引
Using index conditio,使用到索引過濾
Using MRR,使用到索引內部排序
Using where,使用到where條件
Using temporary,使用到臨時表
-
Using index 索引覆蓋,也就是不止要使用到索引,而且沒有回表查詢 舉個例子說明
這兩個查詢中,條件都是一樣,但是第一個返回的是所有列,而索引 IX_age上僅包含主鍵列跟索引鍵值,故需要再根據主鍵的值去PK樹上找到對應的列,這個操作稱爲回表,所以第一個查詢中extra沒有USING INDEX,而第二個查詢有。 -
Using index conditio,簡稱 ICP
-
Using MRR,簡稱 MRR
-
Using where 根據where條件,先取出數據,再跟其他表格關聯查詢
-
Using filesort,無法利用索引來完成的排序
-
Using temporary,使用到臨時表
使用到臨時表,表數量較少的情況下,臨時表使用緩存,但是比較大的時候,則會磁盤存儲,這種情況下,性能將會急劇下降