你會看 MySQL 的執(zhí)行計劃(EXPLAIN)嗎?

SQL 執(zhí)行太慢怎么辦?我們通常會使用 EXPLAIN 命令來查看 SQL 的執(zhí)行計劃,然后根據(jù)執(zhí)行計劃找出問題所在并進行優(yōu)化。
用法簡介
EXPLAIN 的用法很簡單,只需要在你的 SQL 前面加上 EXPLAIN 即可。例如:
PS:insert、update、delete 同樣可以通過 explain 查看執(zhí)行計劃,不過通常我們更關(guān)心 select 的執(zhí)行情況
你會看到如下輸出:
執(zhí)行計劃結(jié)果字段說明如下表:

因此,我們需要知道每個字段代表什么指標(biāo);什么樣的取值是我們想要的,什么樣是需要優(yōu)化的;最后還要知道如何優(yōu)化成我們想要的值。
字段詳解
id
標(biāo)識符。查詢操作的序列號。通常都是正整數(shù),但當(dāng)有 UNION 操作時,該值可以為 NULL。
id 相同
id 不同
id 包含 NULL
id 為 NULL 時,table 列值為 < unionM,n > 格式,表示該行為 id 為 m 和 n 聯(lián)合的結(jié)果
id 順序的規(guī)則:如果 id 相同,執(zhí)行順序由上到下;如果不同,執(zhí)行順序由大到小。
select_type
SELECT 類型,常見的取值如下表:

type
連接字段為主鍵或者唯一索引,此類型通常出現(xiàn)于多表的join查詢,表示對于前表的每一個結(jié)果,都對應(yīng)后表的唯一一條結(jié)果。并且查詢的比較是=操作,查詢效率比較高。

還有一種 NULL 的情況,比如 select min(id) from t1,但 MySQL 官方?jīng)]有提及這種情況,所以我們不在此討論
性能從優(yōu)到劣依次為:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
優(yōu)化原則:最好做到 const,至少做到 ref,避免 ALL
ref
查詢中用來和索引比較的類型,如:id = 1,值為 const;如果是聯(lián)合查詢或者子查詢則為關(guān)聯(lián)的字段;如果使用了函數(shù),則為 func。
Extra
Extra 用來存放一些附加信息,通常用來配合 type 的輸出來做 SQL 優(yōu)化。
擴展
desc
desc 與 explain 作用相同,可以互相代替,后面的例子中均使用 desc 來查看執(zhí)行計劃。
format
explain/desc 還支持一些參數(shù),format 顧名思義,是用來格式化輸出結(jié)果的。它包括兩種格式化方式:tree 和 json。
比如:
輸出格式如下:
執(zhí)行計劃結(jié)果以樹形結(jié)構(gòu)展示,可以清晰的看出語句之間的嵌套關(guān)系,還有基本的執(zhí)行成本(cost)。
使用 json 方式:
輸出結(jié)構(gòu)為一個 JSON 結(jié)構(gòu):
簡介表中的 JSON Name 指的就是這里 JSON 結(jié)果的 key
json 格式會展示出更加詳細(xì)的信息,可以看到執(zhí)行成本劃分的更加細(xì)致了,方便定位到慢 SQL 的問題具體出現(xiàn)在哪個環(huán)節(jié)。
analyze
除了 format 以外,explain/desc 還可以使用 analyze 參數(shù):
輸出結(jié)果:
可以看出,analyze 的輸出結(jié)果是基于 format = tree 的
上面執(zhí)行計劃中(format = json/tree)的執(zhí)行成本(cost)都是估值,而 analyze 中的執(zhí)行成本是真實值。actual time 代表對應(yīng) SQL 執(zhí)行的真實時間,單位為毫秒。
最后
執(zhí)行計劃的結(jié)果中,我們最關(guān)心的是 type,它能夠最直接的反映出 SQL 執(zhí)行效率處在什么級別。然后再結(jié)合其他字段(例如 Extra)來做更細(xì)致的分析。還可以通過各種參數(shù),來分解每個環(huán)節(jié)的執(zhí)行情況。
今天的內(nèi)容就到這里,有哪些想要了解的可以留言告訴我。