mysql explain詳解

概念

  • 在日常工作中,我們會(huì)有時(shí)會(huì)開慢查詢?nèi)ビ涗浺恍﹫?zhí)行時(shí)間比較久的SQL語(yǔ)句,找出這些SQL語(yǔ)句并不意味著完事了,些時(shí)我們常常用到explain這個(gè)命令來(lái)查看一個(gè)這些SQL語(yǔ)句的執(zhí)行計(jì)劃,查看該SQL語(yǔ)句有沒(méi)有使用上了索引,有沒(méi)有做全表掃描,這都可以通過(guò)explain命令來(lái)查看。所以我們深入了解MySQL的基于開銷的優(yōu)化器,還可以獲得很多可能被優(yōu)化器考慮到的訪問(wèn)策略的細(xì)節(jié),以及當(dāng)運(yùn)行SQL語(yǔ)句時(shí)哪種策略預(yù)計(jì)會(huì)被優(yōu)化器采用。(QEP:sql生成一個(gè)執(zhí)行計(jì)劃query Execution plan)

  • expain出來(lái)的信息有10列,分別是id、select_type、tabletype、possible_keys、keykey_len、refrows、Extra,下面對(duì)這些字段出現(xiàn)的可能進(jìn)行解釋

參數(shù)詳解

id

  • SQL執(zhí)行的順序的標(biāo)識(shí),SQL從大到小的執(zhí)行
    1. id相同時(shí),執(zhí)行順序由上至下
    2. 如果是子查詢,id的序號(hào)會(huì)遞增,id值越大優(yōu)先級(jí)越高,越先被執(zhí)行
    3. id如果相同,可以認(rèn)為是一組,從上往下順序執(zhí)行;在所有組中,id值越大,優(yōu)先級(jí)越高,越先執(zhí)行

select_type

  • 表示查詢中每個(gè)select子句的類型
類型 解釋
SIMPLE 簡(jiǎn)單SELECT,不使用UNION或子查詢等
PRIMARY 查詢中若包含任何復(fù)雜的子部分,最外層的select被標(biāo)記為PRIMARY
UNION UNION中的第二個(gè)或后面的SELECT語(yǔ)句
DEPENDENT UNION UNION中的第二個(gè)或后面的SELECT語(yǔ)句,取決于外面的查詢
UNION RESULT UNION的結(jié)果
SUBQUERY 子查詢中的第一個(gè)SELECT
DEPENDENT SUBQUERY 子查詢中的第一個(gè)SELECT,取決于外面的查詢
DERIVED 派生表的SELECT, FROM子句的子查詢
UNCACHEABLE SUBQUERY 一個(gè)子查詢的結(jié)果不能被緩存,必須重新評(píng)估外鏈接的第一行

table

  • 顯示這一行的數(shù)據(jù)是關(guān)于哪張表的,有時(shí)不是真實(shí)的表名字,看到的是derivedx(x是個(gè)數(shù)字,我的理解是第幾步執(zhí)行的結(jié)果)

type (重要)

表示MySQL在表中找到所需行的方式,又稱“訪問(wèn)類型”。

常用的類型有:** ALL, index, range, ref, eq_ref, const, system, NULL(從左到右,性能從差到好)**

類型 說(shuō)明
system 該表只有一行(相當(dāng)于系統(tǒng)表),system是const類型的特例
const 針對(duì)主鍵或唯一索引的等值查詢掃描,最多只返回一行數(shù)據(jù),速度非常快,因?yàn)樗恍枰x取一次
eq_ref 當(dāng)使用了索引的全部組成部分,并且索引是PRIMARY KEY或UNIQUE NOT NULL
ref 當(dāng)滿足索引的最左前綴規(guī)則,或者索引不是主鍵也不是唯一索引時(shí)才會(huì)發(fā)送。
fulltext 全文索引
ref_or_null 類似于ref,但mysql會(huì)額外搜索哪些行包含了NULL。常見(jiàn)于解析子查詢
index_merge 使用了索引合并優(yōu)化,表示一個(gè)查詢里用到了多個(gè)索引
unique_subquery 和eq_ref類似,但用了in,且子查詢是主鍵或唯一索引
index_subquery 和unique_subquery類似,只是子查詢用的不是唯一索引
range 范圍掃描。表示檢索了指定范圍的行,主要用于有限制的索引掃描。常見(jiàn)于between或where里有>、<、IS NULL、<=>、LIKE、IN等
index 全索引掃描,與ALL類似,只不過(guò)index是全盤掃描了索引的數(shù)據(jù)。當(dāng)查詢僅使用索引中的一部分列時(shí)(且不符合最左前綴),可使用此類型。有兩個(gè)場(chǎng)景會(huì)觸發(fā):1. 如果索引是查詢的覆蓋索引,并且索引查詢的數(shù)據(jù)就可以滿足查詢中所需的所有數(shù)據(jù),則只掃描索引樹。此時(shí)extra中會(huì)有using index。2. 按照索引的順序來(lái)查找,執(zhí)行了全表掃描。次數(shù)extra不會(huì)出現(xiàn)using index
all 全表掃描,性能最差

possible_keys

  • 指出MySQL能使用哪個(gè)索引在表中找到記錄,查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢使用**
  • 該列完全獨(dú)立于EXPLAIN輸出所示的表的次序。這意味著在possible_keys中的某些鍵實(shí)際上不能按生成的表次序使用。
    如果該列是NULL,則沒(méi)有相關(guān)的索引。在這種情況下,可以通過(guò)檢查WHERE子句看是否它引用某些列或適合索引的列來(lái)提高你的查詢性能。如果是這樣,創(chuàng)造一個(gè)適當(dāng)?shù)乃饕⑶以俅斡肊XPLAIN檢查查詢

Key

  • key列顯示MySQL實(shí)際決定使用的鍵(索引)

  • 如果沒(méi)有選擇索引,鍵是NULL。要想強(qiáng)制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

key_len

  • 表示索引中使用的字節(jié)數(shù),可通過(guò)該列計(jì)算查詢中使用的索引的長(zhǎng)度(key_len顯示的值為索引字段的最大可能長(zhǎng)度,并非實(shí)際使用長(zhǎng)度,即key_len是根據(jù)表定義計(jì)算而得,不是通過(guò)表內(nèi)檢索出的)

  • 不損失精確性的情況下,長(zhǎng)度越短越好

key_len的長(zhǎng)度計(jì)算公式:
varchr(10)變長(zhǎng)字段且允許NULL    =  10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(變長(zhǎng)字段)
varchr(10)變長(zhǎng)字段且不允許NULL =  10 *( character set:utf8=3,gbk=2,latin1=1)+2(變長(zhǎng)字段)

char(10)固定字段且允許NULL        =  10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)
char(10)固定字段且不允許NULL        =  10 * ( character set:utf8=3,gbk=2,latin1=1)

ref

  • 表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值

rows

  • 要掃描的行數(shù)
  • 表示MySQL根據(jù)表統(tǒng)計(jì)信息及索引選用情況,估算的找到所需的記錄所需要讀取的行數(shù)
    需要降低掃描的行數(shù)

filtered

符合查詢條件的數(shù)據(jù)百分比,最大100.用rows* filtered可獲得和下一張表連接的行數(shù)。例如rows = 1000,filtered = 50%,則和下一章表連接的行數(shù)是500

Extra

  • 該列包含MySQL解決查詢的詳細(xì)信息,有以下幾種情況:從上到下變慢

  • Using index:不需要回表,使用索引匹配,且不需要索引范圍掃描

  • Using index & using where:不需要回表,使用索引匹配,但需要索引范圍掃描

  • Using index condition: 在5.6引入的新特性,先條件過(guò)濾索引,過(guò)濾完索引后找到所有符合索引條件的數(shù)據(jù)行,隨后用where中其他條件去過(guò)濾

  • Using where: 意味著通過(guò)索引或者表掃描的方式進(jìn)行where條件的過(guò)濾,反過(guò)來(lái)說(shuō),也就是沒(méi)有可用的索引查找,當(dāng)然這里也要考慮索引掃描+回表與表掃描的代價(jià)。

  • Using temporary:表示MySQL需要使用臨時(shí)表來(lái)存儲(chǔ)結(jié)果集,常見(jiàn)于排序和分組查詢,需要著重優(yōu)化
    query里包含不同列的group by和order by子句,通常會(huì)用到臨時(shí)表

-- name無(wú)索引
explain SELECT name FROM t1 GROUP BY name
  • Using filesort:MySQL中無(wú)法利用索引完成的排序操作稱為“文件排序”
    當(dāng)query中包含order by,且無(wú)法利用索引進(jìn)行排序時(shí),就會(huì)出現(xiàn)using filesort, 需要著重優(yōu)化

  • Using join buffer:改值強(qiáng)調(diào)了在獲取連接條件時(shí)沒(méi)有使用索引,并且需要連接緩沖區(qū)來(lái)存儲(chǔ)中間結(jié)果。如果出現(xiàn)了這個(gè)值,那應(yīng)該注意,根據(jù)查詢的具體情況可能需要添加索引來(lái)改進(jìn)能。

  • Impossible where:這個(gè)值強(qiáng)調(diào)了where語(yǔ)句會(huì)導(dǎo)致沒(méi)有符合條件的行。

  • Select tables optimized away:這個(gè)值意味著僅通過(guò)使用索引,優(yōu)化器可能僅從聚合函數(shù)結(jié)果中返回一行

總結(jié): EXPLAIN不會(huì)告訴你關(guān)于觸發(fā)器、存儲(chǔ)過(guò)程的信息或用戶自定義函數(shù)對(duì)查詢的影響情況

  • EXPLAIN不考慮各種Cache
  • EXPLAIN不能顯示MySQL在執(zhí)行查詢時(shí)所作的優(yōu)化工作
  • 部分統(tǒng)計(jì)信息是估算的,并非精確值
  • EXPALIN只能解釋SELECT操作,其他操作要重寫為SELECT后查看執(zhí)行計(jì)劃。**
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Mysql概述 數(shù)據(jù)庫(kù)是一個(gè)易于訪問(wèn)和修改的信息集合。它允許使用事務(wù)來(lái)確保數(shù)據(jù)的安全性和一致性,并能快速處理百萬(wàn)條...
    彥幀閱讀 13,962評(píng)論 10 460
  • 觀其大綱 page 01 基礎(chǔ)知識(shí) 1 MySQL數(shù)據(jù)庫(kù)概要 2 簡(jiǎn)單MySQL環(huán)境 3 數(shù)據(jù)的存儲(chǔ)和獲取 4 M...
    周少言閱讀 3,255評(píng)論 0 33
  • 在日常工作中,我們會(huì)有時(shí)會(huì)開慢查詢?nèi)ビ涗浺恍﹫?zhí)行時(shí)間比較久的SQL語(yǔ)句,找出這些SQL語(yǔ)句并不意味著完事了,些時(shí)我...
    討厭夏天的胖墩子閱讀 406評(píng)論 0 0
  • MySQL Explain詳解 在日常工作中,我們會(huì)有時(shí)會(huì)開慢查詢?nèi)ビ涗浺恍﹫?zhí)行時(shí)間比較久的SQL語(yǔ)句,找出這些S...
    鮑陳飛閱讀 1,722評(píng)論 0 1
  • 在日常工作中,我們會(huì)有時(shí)會(huì)開慢查詢?nèi)ビ涗浺恍﹫?zhí)行時(shí)間比較久的SQL語(yǔ)句,找出這些SQL語(yǔ)句并不意味著完事了,有些時(shí)...
    一個(gè)菜鳥JAVA閱讀 305評(píng)論 0 0

友情鏈接更多精彩內(nèi)容