MySQL高級(三)、使用Explain進行SQL性能分析

在MySQL的邏輯架構的第二層服務層中有一個優化器(Optimizer),該優化器能以它自己認可的一種方式優化底層MySQL的執行順序。使用EXPLAIN關鍵字可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理SQL語句的。分析查詢語句或是表結構的性能瓶頸。

MySQL常見瓶頸

MySQL的常見瓶頸分爲以下幾類:

  • CPU:SQL中對大量數據進行比較、關聯、排序、分組(最大的壓力在於比較)
  • IO:實例內存滿足不了緩存數據或排序等需要,導致產生大量物理 IO。查詢執行效率低,掃描過多數據行。
  • 鎖:不適宜的鎖的設置,導致線程阻塞,性能下降。死鎖,線程之間交叉調用資源,導致死鎖,程序卡住。
  • 服務器硬件的性能瓶頸:使用top,free, iostat和vmstat來查看系統的性能狀態

Explain

Explain用途

先簡單看一下Explain的用途,初次看下面羅列的幾點你可能並不知道在說啥,但通過接下來的學習,回過頭來看時就會明瞭了。

  1. 查看錶的讀取順序
  2. 哪些索引可以使用
  3. 數據讀取操作的操作類型
  4. 哪些索引被實際使用
  5. 表之間的引用
  6. 每張表有多少行被優化器查詢

Explain使用

語法: Expalin + 一條完整的SQL語句。
如:explain select * from dept;
在這裏插入圖片描述

注意:在5.7以前的版本中,想要顯示partitions需要使用explain partitions命令;想要顯示filtered需要使用explain extended命令。在5.7版本後,默認explain直接顯示partitions和filtered中的信息。

各字段含義

1. id

select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序。執行順序描述如下:id值相同時,執行順序由上至下;id值不同時,數字越大的越先執行
案例:查看下面的執行語句分析MySQL的執行順序。

EXPLAIN SELECT t2.* FROM t2, (SELECT * FROM t3 WHERE t3.content='') s3 WHERE s3.id=t2.id;

在這裏插入圖片描述
解釋:我們看id列,1,1,2三個數值,數字越大越先執行,2對應的表爲t3表,所以先讀取t3表,即執行(SELECT * FROM t3 WHERE t3.content=’ '),然後兩個1相同,則自上往下順序執行,先讀取derived2即有id爲2的衍生出的衍生表s3,最後再讀取t2表。(此圖爲5.5版本)

2. select_type

select_type用來指明查詢類型,可能的取值如下:
在這裏插入圖片描述
含義:

  • simple:表示不需要union操作或者不包含子查詢的簡單select查詢。有連接查詢時,外層的查詢爲simple,且只有一個。
  • primary:一個需要union操作或者含有子查詢的select,位於最外層的查詢即爲primary。且只有一個。
  • union:union連接的select查詢,除了第一個表外,第二個及以後的表查詢都是union。
  • dependent union:與union一樣,出現在union 或union all語句中,但是這個查詢要受到外部查詢的影響
  • union result:包含union的結果集,在union和union all語句中,因爲它不需要參與查詢,所以id字段爲null
  • subquery:除了from子句中包含的子查詢外,其他地方出現的子查詢都可能是subquery
  • dependent subquery:與dependent union類似,表示這個subquery的查詢要受到外部表查詢的影響
  • derived:from子句中出現的子查詢。
  • materialized:被物化的子查詢
  • UNCACHEABLE SUBQUERY:對於外層的主表,子查詢不可被物化,每次都需要計算(耗時操作)
  • UNCACHEABLE UNION:UNION操作中,內層的不可被物化的子查詢(類似於UNCACHEABLE SUBQUERY)

3. table

表示這一行的數據是關於哪張表的,可以是真實的表名,也可以是衍生表,如< derived N>表示該表來自於某個查詢衍生出來的,後邊的N就是執行計劃中的id。<union M,N>表示這個結果來自於union查詢的id爲M,N的結果集。

4. partitions

版本5.7以前,該項是explain partitions顯示的選項,5.7以後成爲了默認選項。該列顯示的爲分區表命中的分區情況。非分區表該字段爲空(null)。

5. type

type是訪問類型,可能的取值按從好到壞的排序依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range(儘量保證) > index > ALL

需要記住的是:system>const>eq_ref>ref>range>index>ALL
一般來說,得保證查詢至少達到range級別,最好能達到ref級別

  • system:表中只有一行數據,且只能用於myisam和memory表。如果是Innodb引擎表,type列在這個情況通常都是all或者index。這是const類型的特列,平時不會出現,這個也可以忽略不計。
  • const:使用主鍵或者唯一索引(primary key 或者 unique key),只匹配一行數據,也叫做唯一索引掃描。
  • eq_ref:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描,如一個公司的CEO只有一個,對應的部門爲總裁辦,只有一條記錄與之對應。
  • ref:非唯一性索引掃描,返回匹配某個單獨值的所有行。本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,所以他應該屬於查找和掃描的混合體。
  • range:只檢索給定範圍的行,索引範圍掃描,常見於使用 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN()或者like等運算符的查詢中。
  • index:Full Index Scan全索引掃描,index與ALL區別爲index類型只遍歷索引樹。這通常比ALL快,因爲索引文件通常比數據文件小。(也就是說雖然all和Index都是讀全表,但index是從索引中讀取的,而all是從硬盤中讀取的)
  • all:Full Table Scan全表掃描,將遍歷全表以找到匹配的行
  • index_merge:表示查詢使用了兩個及以上的索引,通常出現在有 or 的關鍵字的sql中
  • ref_or_null:對於某個字段既需要關聯條件,也需要null值得情況下。查詢優化器會選擇用ref_or_null連接查詢。
    例如:SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
  • unique_subquery:用於where中的in形式子查詢,子查詢返回不重複值唯一值
  • index_subquery:用於in形式子查詢使用到了輔助索引或者in常數列表,子查詢可能返回重複值,可以使用索引將子查詢去重。

6. possible_keys

顯示可能應用在這張表中的索引,一個或多個。查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢實際使用

7.key

實際使用的索引。如果爲NULL,則沒有使用索引。查詢中若使用了覆蓋索引,則該索引和查詢的select字段重疊,顯示的key爲索引名稱。

8. key_len

表示索引中使用的字節數,可通過該列計算查詢中使用的索引的長度。key_len字段能夠幫你檢查是否充分的利用上了索引。key_len只計算where條件用到的索引長度,而排序和分組就算用到了索引,也不會計算到key_len中。

9. ref

顯示索引的哪一列被使用了,如果可能的話,是一個常數。哪些列或常量被用於查找索引列上的值。
在這裏插入圖片描述

10.rows

rows列顯示MySQL認爲它執行查詢時必須檢查的行數。估算出的行數值,不是精確值。行數越少越好。

11. filtered

使用explain extended時會出現這個列,5.7之後的版本默認就有這個字段,不需要使用explain extended了。這個字段表示存儲引擎返回的數據在server層過濾後,剩下多少滿足查詢的記錄數量的比例,注意是百分比,不是具體記錄數。

12. extra

包含不適合在其他列中顯示但十分重要的額外信息。
這一列可以顯示的信息有:

  1. using filesort:說明mysql會對數據使用一個外部的索引排序,而不是按照表內的索引順序進行讀取。
    MySQL中無法利用索引完成的排序操作稱爲“文件排序”。
  2. using temporary:使用了臨時表保存中間結果,MySQL在對查詢結果排序時使用臨時表。常見於排序 order by 和分組查詢 group by
  3. using index:表示相應的select操作中使用了覆蓋索引(Covering Index),避免訪問了表的數據行,效率不錯!如果同時出現using where,表明索引被用來執行索引鍵值的查找;
    如果沒有同時出現using where,表明索引只是用來讀取數據而非利用索引執行查找。
  4. using where:表明使用了where過濾
  5. using join buffer:使用了連接緩存
  6. impossible where:where子句的值總是false,不能用來獲取任何元組

注意:若出現上述紅色的提示信息,則需要對查詢語句進行相應的優化了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章