MySQL性能優化(四)-- MySQL explain詳解

轉載地址:http://www.javashuo.com/article/p-kftdkiis-cq.htmljava

MySQL中的explain命令顯示了mysql如何使用索引來處理select語句以及鏈接表。explain顯示的信息能夠幫助選擇更好的索引和寫出更優化的查詢語句。mysql

1、格式

explain + select 語句;web

例如:explain select * from tb_student;sql

2、5.5和5.7版本explain的區別

5.7以後的版本默認會有 partitions 和 filtered兩列,可是5.5版本中是沒有的,須要post

使用explain partitions select ……來顯示帶有partitions 的列,性能

使用explain extended select ……來顯示帶有filtered的列。優化

本文是基於5.5.54版本的。spa

3、explain的做用

1.描述MySQL如何執行查詢操做、執行順序,使用到的索引,以及MySQL成功返回結果集須要執行的行數。code

2.能夠幫助咱們分析 select 語句,讓咱們知道查詢效率低下的緣由,從而改進咱們的查詢,讓查詢優化器可以更好的工做orm

查詢優化器的做用:

1.優化select 語句,分析哪些是常量表達式(例如id=1),以及分析哪些表達式能夠直接轉換成常量的

2.對where條件進行簡化和轉換,如去掉無用條件,調整條件結構等

3.讀取涉及的表的統計信息,並計算分析(例如返回的行數,索引信息等),最終得出執行計劃

4、執行計劃(QEP)包含的信息

 

img

 

  1. id:標識符,表示執行順序
  2. select _type:查詢類型
  3. table:輸出行所引用的表
  4. partitions:使用的哪一個分區,須要結合表分區才能夠看到
  5. type:表示按某種類型來查詢,例如按照索引類型查找,按照範圍查找。從最好到最差的鏈接類型爲const、eq_reg、ref、range、indexhe和all
  6. possible_keys:可能用到的索引,保存的是索引名稱,若是是多個索引的話,用逗號隔開
  7. key:實際用到的索引,保存的是索引名稱,若是是多個索引的話,用逗號隔開
  8. key_len:表示本次查詢中,所選擇的索引長度有多少字節
  9. ref:顯示索引的哪一列被使用了,若是可能的話,是一個常數
  10. rows:顯示mysql認爲執行查詢時必需要返回的行數
  11. filtered:經過過濾條件以後對比總數的百分比
  12. extra:額外的信息,例如:using file sort ,using where, using join buffer,using index等

5、執行計劃中各個參數的詳解

1.id

表示select標識符,同時代表執行順序,也就是說id是一個查詢的序列號,查詢序號即爲sql語句執行的順序。

(1)當id值相同時,按從上到下的順序執行

(2)當id所有不一樣時,按id從大到小執行

(3)當id部分不一樣時,先執行id大的,id相同的,按從上到下的順序執行

2.select_type

(1)simple:表示簡單的select,沒有union和子查詢

(2)primary:最外面的查詢 或者 主查詢,在有子查詢的語句中,最外面的select查詢就是primary

(3)subquery:子查詢

(4)union:union語句的第二個或者說是後面那一個select

(5)union result:union以後的結果

(6)dependent unoin:unoin 中的第二個或隨後的 select 查詢,依賴於外部查詢的結果集

(7)dependent subquery:子查詢中的第一個 select 查詢,依賴於外部 查詢的結果集

(8)derived:衍生表(5.7版本中不存在這一個)

3.table

一般是表名,或者表的別名,或者一個爲查詢產生臨時表的標示符(如派生表、子查詢、集合)

4.partitions

使用的哪些分區(對於非分區表值爲null),在5.5版本中須要加上explain partitions select .....

5.type

(1)const:表中最多有一個匹配行,const用於比較primary key 或者unique索引。由於只匹配一行數據,因此很快

(2)eq_ref:惟一性索引掃描,對於每一個來自於前面的表的記錄,從該表中讀取惟一一行

(3)ref:非惟一性索引掃描,對於每一個來自於前面的表的記錄,全部匹配的行從這張表取出

(4)ref_or_null:相似於ref,可是能夠搜索包含null值的行,例如:select * from student where address='xxx' or address is null,須要在address創建索引。

(5)index_merge:查詢語句用到了一張表的多個索引時,mysql會將多個索引合併到一塊兒

(6)range:按指定範圍(如in、<、>、between and等,可是前提是此字段要創建索引)來檢索,很常見。如:select * from student where id < 5,id上要有索引。

(7)index:全」表「掃描,可是是在索引樹中掃描,一般比ALL快,由於索引文件一般比數據文件小,index掃描是經過二叉樹的方式掃描,而all是掃描物理表。(也就是說雖然all和index都是讀全表,但index是從索引中讀取的,而all是從硬盤中讀的)。例如:select name from student,但name字段上須要創建索引,也就是查詢的字段屬於索引中的字段。

(8)all:全表掃描,掃描完整的物理表,此時就須要優化了。

6.possible_keys

指出 MySQL 能在該表中可能使用的索引,顯示的是索引的名稱,多個索引用逗號隔開,若是沒有,則爲null。

7.key

MySQL決定實際用到的索引,顯示的是索引的名稱,多個索引用逗號隔開,若是沒有,則爲null

8.key_len

當用到組合索引的時候判斷索引是否徹底用上。

實例:假設student表中有id int,name char(20) DEFAULT NULL,address varchar(20) DEFAULT NULL,remark varchar(20) NOT NULL 字段,創建的索引是 idx_address_remark(在address和remark上創建的組合索引)

查詢的sql是:select * from student where address='深圳' and remark='java coder',此時,執行計劃中的key_len是 (203+1+2)+ (203+2)= 125,那麼這個是怎麼得來的呢?

解析:20表示建表的時候 varchar(20) ,3表示utf8字符集佔用3個字節,1表示MySQL須要1個字節表示null,2表示變長字段(varchar是變長的)。  

假設drop掉剛剛創建的索引,新建索引 idx_name_address(在name和address上創建組合索引)

查詢的sql是:select * from student where name='xbq' and address='深圳',此時,執行計劃中的key_len是 (203+1)+ (203+2)= 123,那麼這個值是怎麼得來的呢?

解析:20表示建表的時候 char(20) ,3表示utf8字符集佔用3個字節,1表示MySQL須要1個字節標識null,即 20*3+1,後面的一樣的道理。

key_len只計算where條件用到的索引長度,而排序和分組就算用到了索引,也不會計算到key_len中。

計算key_len的公式:

varchr(10)變長字段且容許NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1) + 1(NULL) + 2(變長字段)

varchr(10)變長字段且不容許NULL = 10 *( character set:utf8=3,gbk=2,latin1=1) + 2(變長字段)

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)

9.ref

顯示索引的哪一列被使用了,若是可能的話,是一個常數

10.rows

顯示mysql認爲執行查詢時必需要返回的行數,可結合type和key分析,沒有用上索引的狀況下,會全表掃描。rows的值越小越好,說明檢索的數據少

11.filtered

給出了一個百分比的值,這個百分比值和rows列的值一塊兒使用,能夠估計出那些將要和執行計劃中的前一個表(前一個表就是指id列的值比當前表的id小的表)進行鏈接的行的數目。

這一列在5.5版本中,須要加上 explain extended select ....。

12.extra

此字段顯示一些額外的信息,可是此字段的部分值具備優化的參考意義。

(1)using where:表示查詢使用了where 語句來處理結果

(2)using index:表示使用了覆蓋索引。這個值重點強調了只須要使用索引就能夠知足查詢表的要求,不須要直接訪問表數據。

(3)using join buffer:這個值強調了在獲取鏈接條件時沒有使用索引,而且須要鏈接緩衝區來存儲中間結果。若是出現了這個值,那應該注意,根據查詢的具體狀況可能須要添加索引來改進性能

(4)using filesort:這是 order by 語句的結果。這多是一個CPU密集型的過程。using filesort表示出現了文件內排序,表示很很差的現象,必需要優化,特別是大表,能夠經過選擇合適的索引來改進性能,用索引來爲查詢結果排序。

(5)using temporary:mysql須要建立一張臨時表來保存中間結果。 也就是說,須要先把數據放到臨時表中,而後從臨時表中獲取須要的數據。出現這種臨時表,也是必須須要優化的地方,特別是數據量大的狀況。兩個常見的緣由是在來自不一樣表的列上使用了distinct,或者使用了不一樣的 order by 和 group by 列。

做者:碼咖 連接:https://juejin.im/post/5d141528e51d4577565367d0 來源:掘金 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索