MySQL執(zhí)行計(jì)劃的深入分析
前言
在之前的面試過程中,問到執(zhí)行計(jì)劃,有很多童鞋不知道是什么?甚至將執(zhí)行計(jì)劃與執(zhí)行時(shí)間認(rèn)為是同一個(gè)概念。今天我們就一起來了解一下執(zhí)行計(jì)劃到底是什么?有什么用途?
執(zhí)行計(jì)劃是什么?
執(zhí)行計(jì)劃,簡單的來說,是SQL在數(shù)據(jù)庫中執(zhí)行時(shí)的表現(xiàn)情況,通常用于SQL性能分析,優(yōu)化等場景。
一. 執(zhí)行計(jì)劃能告訴我們什么?
- SQL如何使用索引
- 聯(lián)接查詢的執(zhí)行順序
- 查詢掃描的數(shù)據(jù)函數(shù)
二. 執(zhí)行計(jì)劃中的內(nèi)容

SQL執(zhí)行計(jì)劃的輸出可能為多行,每一行代表對(duì)一個(gè)數(shù)據(jù)庫對(duì)象的操作
1. ID列
- ID列中的如果數(shù)據(jù)為一組數(shù)字,表示執(zhí)行SELECT語句的順序;如果為NULL,則說明這一行數(shù)據(jù)是由另外兩個(gè)SQL語句進(jìn)行 UNION操作后產(chǎn)生的結(jié)果集
- ID值相同時(shí),說明SQL執(zhí)行順序是按照顯示的從上至下執(zhí)行的
- ID值不同時(shí),ID值越大代表優(yōu)先級(jí)越高,則越先被執(zhí)行
演示

可以看到上面的執(zhí)行計(jì)劃返回了3行結(jié)果,id列的值可以看作是SQL中所具有的SELECT操作的序號(hào)
由于上述SQL中只有一個(gè)SELECT,所以id全為1,因此,我們就要按照由上至下讀取執(zhí)行計(jì)劃
按照我們的SQL語句,我們會(huì)認(rèn)為執(zhí)行順序是a,b,c,但是通過上圖可以發(fā)現(xiàn),Mysql并不是完成按照SQL中所寫的順序來進(jìn)行表的關(guān)聯(lián)操作的
執(zhí)行對(duì)表的執(zhí)行順序?yàn)閍,c,b,這是由于MySQL優(yōu)化器會(huì)根據(jù)表中的索引的統(tǒng)計(jì)信息來調(diào)整表關(guān)聯(lián)的實(shí)際順序
2. SELECT_TYPE列
| 值 | 含義 |
|---|---|
| SIMPLE | 不包含子查詢或是UNION操作的查詢 |
| PRIMARY | 查詢中如果包含任何子查詢,那么最外層的查詢則被標(biāo)記為PRIMARY |
| SUBQUERY | SELECT 列表中的子查詢 |
| DEPENDENT SUBQUERY | 依賴外部結(jié)果的子查詢 |
| UNION | Union操作的第二個(gè)或是之后的查詢的值為union |
| DEPENDENT UNION | 當(dāng)UNION作為子查詢時(shí),第二或是第二個(gè)后的查詢的select_type值 |
| UNION RESULT | UNION產(chǎn)生的結(jié)果集 |
| DERIVED | 出現(xiàn)在FROM子句中的子查詢 |
3. TABLE列
包含以下幾種結(jié)果:
輸出去數(shù)據(jù)行所在表的名稱,如果表取了別名,則顯示的是別名
<union M,N>: 由ID為M,N查詢union產(chǎn)生的結(jié)果集
<derived N>/<subquery N> :由ID為N的查詢產(chǎn)生的結(jié)果
4. PARTITIONS列:
查詢匹配的記錄來自哪一個(gè)分區(qū)
對(duì)于分區(qū)表,顯示查詢的分區(qū)ID
對(duì)于非分區(qū)表,顯示為NULL
5. TYPE列
按性能從高至低排列如下:
| 值 | 含義 |
|---|---|
| system | 這是const聯(lián)接類型的一個(gè)特例,當(dāng)查詢的表只有一行時(shí)使用 |
| const | 表中有且只有一個(gè)匹配的行時(shí)使用,如對(duì)主鍵或是唯一索引的查詢,這是效率最高的聯(lián)接方式 |
| eq_ref | 唯一索引或主鍵索引查詢,對(duì)應(yīng)每個(gè)索引鍵,表中只有一條記錄與之匹配 |
| ref | 非唯一索引查找,返回匹配某個(gè)單獨(dú)值的所有行 |
| ref_or_null | 類似于ref類型的查詢,但是附加了對(duì)NULL值列的查詢 |
| index_merge | 該聯(lián)接類型表示使用了索引合并優(yōu)化方法 |
| range | 索引范圍掃描,常見于between、>、<這樣的查詢條件 |
| index | FULL index Scan 全索引掃描,同ALL的區(qū)別是,遍歷的是索引樹 |
| ALL | FULL TABLE Scan 全表掃描,這是效率最差的聯(lián)接方式 |
6. Extra列
包含MySQL如何執(zhí)行查詢的附加信息
| 值 | 含義 |
|---|---|
| Distinct | 優(yōu)化distinct操作,在找到第一個(gè)匹配的元素后即停止查找 |
| Not exists | 使用not exists來優(yōu)化查詢 |
| Using filesort | 使用額外操作進(jìn)行排序,通常會(huì)出現(xiàn)在order by或group by查詢中 |
| Using index | 使用了覆蓋索引進(jìn)行查詢 |
| Using temporary | MySQL需要使用臨時(shí)表來處理查詢,常見于排序,子查詢,和分組查詢 |
| Using where | 需要在MySQL服務(wù)器層使用WHERE條件來過濾數(shù)據(jù) |
| select tables optimized away | 直接通過索引來獲得數(shù)據(jù),不用訪問表,這種情況通常效率是最高的 |
7. POSSIBLE_KEYS列
指出MySQL能使用哪些索引來優(yōu)化查詢
查詢列所涉及到的列上的索引都會(huì)被列出,但不一定會(huì)被使用
8. KEY列
查詢優(yōu)化器優(yōu)化查詢實(shí)際所使用的索引
如果表中沒有可用的索引,則顯示為NULL
如果查詢使用了覆蓋索引,則該索引僅出現(xiàn)在Key列中
9. KEY_LEN列
顯示MySQL索引所使用的字節(jié)數(shù),在聯(lián)合索引中如果有3列,假如3列字段總長度為100個(gè)字節(jié),Key_len顯示的可能會(huì)小于100字節(jié),比如30字節(jié),這就說明在查詢過程中沒有使用到聯(lián)合索引的所有列,只是利用到了前面的一列或2列
- 表示索引字段的最大可能長度
- Key_len的長度由字段定義計(jì)算而來,并非數(shù)據(jù)的實(shí)際長度
10. Ref列
表示當(dāng)前表在利用Key列記錄中的索引進(jìn)行查詢時(shí)所用到的列或常量
11. rows列
- 表示MySQL通過索引的統(tǒng)計(jì)信息,估算出來的所需讀取的行數(shù)(關(guān)聯(lián)查詢時(shí),顯示的是每次嵌套查詢時(shí)所需要的行數(shù))
- Rows值的大小是個(gè)統(tǒng)計(jì)抽樣結(jié)果,并不十分準(zhǔn)確
12. Filtered列
- 表示返回結(jié)果的行數(shù)占需讀取行數(shù)的百分比
- Filtered列的值越大越好(值越大,表明實(shí)際讀取的行數(shù)與所需要返回的行數(shù)越接近)
- Filtered列的值依賴統(tǒng)計(jì)信息,所以同樣也不是十分準(zhǔn)確,只是一個(gè)參考值
三. 執(zhí)行計(jì)劃的限制
- 無法展示存儲(chǔ)過程,觸發(fā)器,UDF對(duì)查詢的影響
- 無法使用EXPLAIN對(duì)存儲(chǔ)過程進(jìn)行分析
- 早期版本的MySQL只支持對(duì)SELECT語句進(jìn)行分析
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Mysql用戶創(chuàng)建以及權(quán)限賦予操作的實(shí)現(xiàn)
在MySQL中,創(chuàng)建新用戶并為其授予權(quán)限是一項(xiàng)常見的操作,本文主要介紹了Mysql用戶創(chuàng)建以及權(quán)限賦予操作的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
MySQL中使用JSON存儲(chǔ)數(shù)據(jù)的實(shí)現(xiàn)示例
本文主要介紹了MySQL中使用JSON存儲(chǔ)數(shù)據(jù)的實(shí)現(xiàn)示例,我們可以在MySQL中直接存儲(chǔ)、查詢和操作JSON數(shù)據(jù),具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09
MySQL group by和left join并用解決方式
這篇文章主要介紹了MySQL group by和left join并用解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Mybatis報(bào)錯(cuò): org.apache.ibatis.exceptions.PersistenceException
這篇文章主要介紹了Mybatis報(bào)錯(cuò): org.apache.ibatis.exceptions.PersistenceException解決辦法的相關(guān)資料,需要的朋友可以參考下2016-12-12

