MySQL——SQL性能分析優(yōu)化利器之Explain

系統(tǒng)性能的優(yōu)劣取決于我們sql的查詢速度,MySQL Explain命令是分析SQL性能及優(yōu)化不可缺少的一部分。
Explain被我們稱為解釋器,通過 explain 我們可以知道以下信息:表的讀取順序,數(shù)據(jù)讀取操作的類型,可能會使用哪些索引,實際真正使用了哪些索引,表之間的引用,每張表有多少行被優(yōu)化器查詢等信息。

Explain基本語法

explain [extended|partition]select

在select前加explain關(guān)鍵字,MySQL會返回該查詢的執(zhí)行計劃而不是執(zhí)行這條SQL

根據(jù)語法我們知道explain還有兩種其他的用法:

  1. explain extended :能夠在原本explain的基礎(chǔ)上額外的提供一些查詢優(yōu)化的信息,這些信息可以通過mysql的show warnings命令得到,從而看出優(yōu)化器優(yōu)化了什么。

  2. explain partitions:相比 explain 多了個 partitions 字段,如果查詢是基于分區(qū)表的話,會顯示查詢將訪問的分區(qū)。

Explain列的含義

id:id列的編號是 select 的序列號,有幾個 select 就有幾個id,id不同,id值越大,優(yōu)先級越高,越先 執(zhí)行

select_type :顯示本行是簡單或復(fù)雜select。如果查詢有任何復(fù)雜的子查詢,則最外層標記為 PRIMARY(DERIVED、UNION、UNION RESUlT)

table :訪問查詢的表名或表別名|

type :表的訪問類型( MySQL 如何查詢表中的行記錄)效率高低:const eq_ref/ref/range/index/all

possible_keys:指出MySQL能使用哪個索引在該表中找到行

key :MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL

key_len :實際使用的索引長度(單位:字節(jié))該字段顯示為索引字段的最大可能長度,并非實際使 用長度。

ref :用于索引查找的值的來源,如果值未常量,則 ref 為 const

rows :預(yù)計查詢需要掃描的行數(shù)(在表或索引樹中)

filtered :查詢條件所過濾的行記錄數(shù)占比

Extra:額外的信息:

  • Using filesort:說明mysql會對數(shù)據(jù)適用一個外部的索引排序。而不是按照表內(nèi)的索引順序進行讀取。MySQL中無法利用索引完成排序操作稱為“文件排序”
  • Using temporary:使用了臨時表保存中間結(jié)果,mysql在查詢結(jié)果排序時使用臨時表。常見于排序order by和分組查詢group by。
  • Using index:表示相應(yīng)的select操作用使用覆蓋索引,避免訪問了表的數(shù)據(jù)行。如果同時出現(xiàn)using where,表名索引被用來執(zhí)行索引鍵值的查找;如果沒有同時出現(xiàn)using where,表名索引用來讀取數(shù)據(jù)而非執(zhí)行查詢動作。
  • Using where :表明使用where過濾
  • using join buffer:使用了連接緩存
  • impossible where:where子句的值總是false,不能用來獲取任何元組
  • select tables optimized away:在沒有g(shù)roup by子句的情況下,基于索引優(yōu)化Min、max操作或者對于MyISAM存儲引擎優(yōu)化count(*),不必等到執(zhí)行階段再進行計算,查詢執(zhí)行計劃生成的階段即完成優(yōu)化。
    distinct:優(yōu)化distinct操作,在找到第一匹配的元組后即停止找同樣值的動作
    詳細介紹列的含義

1. id列

id 的值為數(shù)值,其表示的是SQL執(zhí)行中的執(zhí)行順序,規(guī)則如下:

如果 id 值相同,則執(zhí)行順序為:從上到下
如果 id 值不同,則執(zhí)行順序為: id 值越大的越先執(zhí)行
如果 id 值相同,則可以認為他們是同一分組,同一分組中執(zhí)行順序為:從上到下
在所有組中, id 值越大的越先執(zhí)行
如果 id 值為 null ,則表示這是一個臨時表,臨時表不在SQL總出現(xiàn),因此它的id是NULL
MySQL將 select 查詢分為簡單查詢和復(fù)雜查詢。復(fù)雜查詢分為三類:簡單子查詢、派生表(from語句中的子查詢)、union 查詢。

2. select_type列

這一列表示的是對應(yīng)行對應(yīng)的查詢類型,到底是簡單查詢還是復(fù)雜查詢,如果是復(fù)雜的查詢,又是簡單子查詢、from語句中的子查詢、union 查詢復(fù)雜查詢中的哪一種。

  1. simple :簡單的select查詢,查詢中不包含子查詢或者 union

  2. primary:復(fù)雜查詢最外層的查詢類型

  3. subquery :在 select 或 where 列表中包含了子查詢

  4. derived:包含在 from 子句中的子查詢。MySQL會將結(jié)果存放在一個臨時表中,也稱為派生表

  5. union:union查詢語句出現(xiàn)在union之后的第二個和以后的查詢會被標為union類型

  6. union result:從 union 構(gòu)建的臨時表檢索結(jié)果的查詢類型

  7. table列

這一列看名稱就知道是指的具體查詢的table名稱。

當 from 子句中有子查詢時,table列是 <derivenN> 格式,表示當前查詢依賴 id=N 的查詢,于是先執(zhí)行 id=N 的查詢。當有 union 時,UNION RESULT 的 table 列的值為 <union1,2>,1和2表示參與 union 的 select 行id。

4. type列

這一列表示關(guān)聯(lián)類型或訪問類型,即MySQL決定如何查找表中的行

最優(yōu)到最差分別為:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

  1. const, system:Mysql查詢對其進行優(yōu)化并轉(zhuǎn)化為一個常量,只查詢一次就搜索出結(jié)果,用于 primary key 或 unique key 的所有列與常數(shù)比較時,所以表最多有一個匹配行,讀取1次,速度比較快。

  2. eq_ref:唯一性索引掃描,對于每個索引鍵,表中只有一條記錄與之匹配。常見于主鍵或唯一索引掃描

  3. ref:相比 eq_ref,不使用唯一索引,而是使用普通索引或者聯(lián)合索引的部分前綴,索引要和某個值相比較,可能會找到多個符合條件的行.

  4. ref_or_null:與ref類型差不多,但是這種類型可以搜索為Null的行

  5. index_merge:使用了索引合并的優(yōu)化方法

6.range: 范圍掃描通常出現(xiàn)在 in(), between ,> ,<, >= 等操作中。使用一個索引來檢索給定范圍的行

7 index:Full Index Scan,Index與All區(qū)別為index類型只遍歷索引樹。這通常比ALL快,因為索引文件通常比數(shù)據(jù)文件小

  1. All:掃描全表,與index其實都是掃描全表進行檢索數(shù)據(jù),區(qū)別在于,index類型是掃描索引樹進行數(shù)據(jù)掃描,而All類型則是直接掃磁盤,所以相對index類型比較慢

5. possible_keys列

顯示此次查詢可能會用到的索引,一個或者是多個,查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定會應(yīng)用。

explain 時可能出現(xiàn) possible_keys 有列,而 key 顯示 NULL 的情況,這種情況是因為表中數(shù)據(jù)不多,mysql認為索引對此查詢幫助不大,選擇了全表查詢。

如果該列是NULL,則沒有相關(guān)的索引。在這種情況下,可以通過檢查 where 子句看是否可以創(chuàng)造一個適當?shù)乃饕齺硖岣卟樵冃阅埽缓笥?explain 查看效果。但是有一種情況也可能會走索引,如果出現(xiàn) 覆蓋索引 的情況即使該列為null 依然有可能會走索引查詢

6. key列

mysql實際采用哪個索引來優(yōu)化對該表的訪問,如果想強制指定索引或者忽視索引,可在查詢中使用 force index、ignore index

7. key_len列

表示索引中使用的字節(jié)數(shù),可通過該列計算查詢中使用的索引的長度,在不損失精確性的情況下,長度越短越好,key_len表示的是索引的最大長度,而不是實際使用長度。

key_len計算規(guī)則如下:

  • 字符型

char(n):n字節(jié)長度
varchar(n):2字節(jié)存儲字符串長度,如果是utf-8,則長度 3n + 2

  • 數(shù)值型

tinyint:1字節(jié)
smallint:2字節(jié)
int:4字節(jié)
bigint:8字節(jié)

  • 時間類型

date:3字節(jié)
timestamp:4字節(jié)
datetime:8字節(jié)

  • 如果字段允許為 NULL,需要額外增加1字節(jié)記錄是否為 NULL

8. ref列

這一列顯示了在key列記錄的索引中,表查找值所用到的列或常量,常見的有:const(常量),func,NULL,字段名

9. rows列

這一列表示這條SQL可能要檢索的數(shù)據(jù)行數(shù),并不是返回結(jié)果集的行數(shù)。

10.Extra列

這一列展示的是一些額外的信息,但是也是十分重要的,對于我們提升SQL 的檢索性能是很有幫助的。

常見的類型如下:

distinct: 一旦mysql找到了與行相聯(lián)合匹配的行,就不再搜索了
Using index:表示相應(yīng)的select操作中使用了覆蓋索引(Covering Index),避免訪問了表的數(shù)據(jù)行,效率還是非常可觀的。
覆蓋索引:簡單的理解就是這次select的字段只從索引中就可以獲取的到,沒有必要再去浪費一次IO讀取行數(shù)據(jù),換句話說就是查詢的列被索引列所覆蓋

Using where:就是使用了where條件查詢。mysql服務(wù)器將在存儲引擎檢索行后再進行過濾。就是先讀取整行數(shù)據(jù),再按 where 條件進行檢查,符合就留下,不符合就丟棄。
Using temporary:mysql需要創(chuàng)建一張臨時表來處理查詢結(jié)果。出現(xiàn)這種情況一般是要進行優(yōu)化的,首先是想到用索引來優(yōu)化。這種類型常見于order by 和group by的查詢中
Using filesort:對查詢結(jié)果進行外部索引排序而不是按索引次序從表里讀取行,這種情況可以考慮建立索引來進行優(yōu)化。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內(nèi)容