MySQL explain 查詢計劃結果集學習筆記

MySQL 的 explain 語句顯示了 MySQL 如何使用索引來處理 select 語句以及連接表,可以幫助我們分析如何選擇更好的索引和寫出更優性能的查詢語句

查詢示例
explain select * from (select * from `user` limit 10, 20) as t1 
left join `user_profile` as t2 on t1.id = t2.user_id;
mysql_explain.png
  1. id(查詢標識符)這是 SELECT 查詢序列號,表明 sql 語句執行的順序,id 列數字越大越先執行,如果數字一樣大,那么就從上往下依次執行,id 列為 null 的就表是這是一個結果集,不需要使用它來進行查詢。例如: explain select * from (select * from `user` limit 10, 10) as s;

    id.png

  2. select_type(查詢類型)常見類型有:

    • simple: 表示不需要 union 操作或者不包含子查詢的 select。有連接查詢時,外層的查詢為 simple,且只有一個
    • primary: 一個需要 union 操作或者含有子查詢的 select,位于最外層的單位查詢的 select_type 即為primary,且只有一個
    • union:union 連接的兩個 select,第一個查詢是 dervied 派生表,除了第一個表外,第二個以后的表的 select_type 都是 union。例如:explain select * from `user` union (select * from `user` limit 10);
      select_type-union.png
      第二條語句就使用了 union。
    • dependent union:與union一樣,出現在 union 或 union all語句中,但是這個查詢要受到外部查詢的影響。
    • union result:包含 union 的結果集,在 union 和 union all 語句中,因為它不需要參與查詢,所以 id 字段為 null。例如:explain select * from `user` union (select * from `user` limit 10);
      select_type-union.png
    • subquery:除了 from 字句中包含的子查詢外,其它地方出現的子查詢都可能是 subquery
    • dependent subquery:與 dependent union 類似,表示這個 subquery 的查詢要受到外部表查詢的影響
    • derived:from 字句中出現的子查詢,也叫做派生表,其他數據庫中可能叫做內聯視圖或嵌套 select。例如: explain select * from (select * from `user` limit 10, 10) as s;
      id.png
  3. table (查詢表名) 如果查詢使用了別名,那么這里顯示的是別名,如果不涉及對數據表的操作,那么這里顯示為 null,如果顯示為尖括號括起來的<derived N>就表示這個是臨時表,后邊的 N 就是執行計劃中的 id,表示結果來自于這個查詢產生。如果是尖括號括起來的<union M,N>,與<derived N>類似,也是一個臨時表,表示這個結果來自于 union 查詢的 id為 M,N 的結果集

  4. type(連接類型)需要重點掌握。有多個參數,依次從好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL. 除了 ALL 之外,其他的 type 都可以使用到索引,除了 index_merge 之外,其他的 type 只可以用到一個索引

    • system:表中只有一行數據或者是空表,且只能用于 MyISAM 和 Memory表。如果是 InnoDB 引擎表,type 列在這個情況通常都是 all 或者 index。
    • const:使用 primary key 或者 unique 索引,返回記錄一定是 1 行記錄的等值 where 條件時,通常 type 是 const。其他數據庫也叫做唯一索引掃描。例如:primary key, explain select * from `user` where id = 1220;
      type-const_1.png
      unique, explain select * from `user` where username = 'fanxin';
      type-const_2.png
    • eq_ref 對于 eq_ref 的解釋,MySQL 手冊是這樣說的:"對于每個來自于前面的表的行組合,從該表中讀取一行。這可能是最好的聯接類型,除了 const 類型。它用在一個索引的所有部分被聯接使用并且索引是 UNIQUE 或 PRIMARY KEY"。eq_ref 可以用于使用=比較帶索引的列。例如:primary key, explain select * from `user` as t1, `user_profile` as t2 where t1.id = t2.user_id;
      type-const_1.png
      unique, explain select * from `user` where username = 'fanxin';
      type-eq_ref.png
    • ref:不像 eq_ref 那樣要求連接順序,也沒有主鍵和唯一索引的要求,只要使用相等條件檢索時就可能出現,常見與輔助索引的等值查找?;蛘叨嗔兄麈I、唯一索引中,使用第一個列之外的列作為等值查找也會出現,總之,返回數據不唯一的等值查找就可能出現。
    • ref_or_null:與 ref 方法類似,只是增加了 null 值的比較。實際用的不多。** 上面這五種情況都是很理想的索引使用情況 **
    • fulltext:全文索引檢索,要注意,全文索引的優先級很高,若全文索引和普通索引同時存在時,MySQL 不管代價,優先選擇使用全文索引。
    • unique_subquery:用于 where 中的 in 形式子查詢,子查詢返回不重復值唯一值。
    • index_subquery:用于 in 形式子查詢使用到了輔助索引或者 in 常數列表,子查詢可能返回重復值,可以使用索引將子查詢去重。
    • range:索引范圍掃描,常見于使用 >, <, is null, between, in, like 等運算符的查詢中。例如:explain select * from `user` where id > 1220;
      type-range.png
    • index_merge:表示查詢使用了兩個以上的索引,最后取交集或者并集,常見and ,or的條件使用了不同的索引,官方排序這個在ref_or_null之后,但是實際上由于要讀取所個索引,性能可能大部分時間都不如 range。
    • index:索引全表掃描,把索引從頭到尾掃一遍,常見于使用索引列就可以處理不需要讀取數據文件的查詢、可以使用索引排序或者分組的查詢。
    • all:這個就是全表掃描數據文件,然后再在server層進行過濾返回符合要求的記錄。
  5. possible_keys(查詢可能使用到的索引)

  6. key(查詢真正使用到的索引)select_type 為 index_merge 時,這里可能出現兩個以上的索引,其他的 select_type 這里只會出現一個。

  7. key_len(用于處理查詢的索引長度)

    • 如果是單列索引,那么整個索引長度都算進去
    • 如果是多列索引,那么查詢不一定都能使用到所有的列,具體使用到了多少個列的索引,這里就會計算進去,沒有使用到的列,這里不會計算進去。留意下這個列的值,算一下你的多列索引總長度就知道有沒有使用到所有的列了。要注意,MySQL 的ICP 特性使用到的索引不會計入其中。另外,key_len 只計算where 條件用到的索引長度,而排序和分組就算用到了索引,也不會計算到 key_len 中。
  8. ref 列顯示使用哪個列或常數與key一起從表中選擇行。如果是使用的常數等值查詢,這里會顯示 const,如果是連接查詢,被驅動表的執行計劃這里會顯示驅動表的關聯字段,如果是條件使用了表達式或者函數,或者條件列發生了內部隱式轉換,這里可能顯示為 func。

  9. rows MySQL 執行查詢的行數,不是精確值。簡單且重要,數值越大越不好,說明沒有用好索引。

  10. Extra 該列包含 MySQL 解決查詢的詳細信息。

    • distinct:在 select 部分使用了 distinc 關鍵字
    • no tables used:不帶 from 字句的查詢或者 From dual 查詢
    • 使用not in()形式子查詢或not exists運算符的連接查詢,這種叫做反連接。即,一般連接查詢是先查詢內表,再查詢外表,反連接就是先查詢外表,再查詢內表。
    • using filesort:排序時無法使用到索引時,就會出現這個。常見于 order by 和 group by 語句中。例如:explain select id,username from user order by created_at;
      extra-using-filesort.png
    • using index:查詢時不需要回表查詢,直接通過索引就可以獲取查詢的數據。
    • using join buffer(block nested loop),using join buffer(batched key accss):5.6.x之后的版本優化關聯查詢的BNL,BKA特性。主要是減少內表的循環數量以及比較順序地掃描查詢。
    • using sort_union,using_union,using intersect,using sort_intersection:using intersect:表示使用 and 的各個索引的條件時,該信息表示是從處理結果獲取交集 using union:表示使用 or 連接各個使用索引的條件時,該信息表示從處理結果獲取并集 using sort_union 和 using sort_intersection:與前面兩個對應的類似,只是他們是出現在用 and 和 or 查詢信息量大時,先查詢主鍵,然后進行排序合并后,才能讀取記錄并返回。
    • 表示使用了臨時表存儲中間結果。臨時表可以是內存臨時表和磁盤臨時表,執行計劃中看不出來,需要查看status變量,used_tmp_table,used_tmp_disk_table才能看出來。
    • using where:表示存儲引擎返回的記錄并不是所有的都滿足查詢條件,需要在 server 層進行過濾。查詢條件中分為限制條件和檢查條件,5.6 之前,存儲引擎只能根據限制條件掃描數據并返回,然后 server 層根據檢查條件進行過濾再返回真正符合查詢的數據。5.6.x 之后支持 ICP 特性,可以把檢查條件也下推到存儲引擎層,不符合檢查條件和限制條件的數據,直接不讀取,這樣就大大減少了存儲引擎掃描的記錄數量。extra 列顯示 using index condition。
    • firstmatch(tb_name):5.6.x 開始引入的優化子查詢的新特性之一,常見于 where 字句含有 in() 類型的子查詢。如果內表的數據量比較大,就可能出現這個。
    • loosescan(m..n):5.6.x 之后引入的優化子查詢的新特性之一,在 in() 類型的子查詢中,子查詢返回的可能有重復記錄時,就可能出現這個。
  11. filtered 使用explain extended時會出現這個列,5.7之后的版本默認就有這個字段,不需要使用explain extended了。這個字段表示存儲引擎返回的數據在server層過濾后,剩下多少滿足查詢的記錄數量的比例,注意是百分比,不是具體記錄數。

參考來源:
mysql explain執行計劃詳解
MYSQL explain詳解

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

推薦閱讀更多精彩內容