EXPLAIN命令顯示了mysql如何使用索引來處理select語句以及鏈接表。能夠幫助選擇更好的索引和寫出更優化的查詢語句。mysql
使用方法,在select語句前加上explain,如:sql
1 | explain select page_id form pic where id=1 |
頭像表-pic(描述用戶頭像地址):優化
# | 名字 | 類型 | 空 | 額外 | 註釋 |
1 | id | int(11) | 否 | AUTO_INCREMENT | 主鍵 |
2 | user_id | int(11) | 否 | user表id | |
3 | url | varchar(64) | 否 | 地址 |
用戶表-user(描述用戶信息):url
# | 名字 | 類型 | 空 | 額外 | 註釋 |
1 | id | int(11) | 否 | AUTO_INCREMENT | 主鍵 |
2 | name | char(38) | 否 | INDEX | 名字 |
3 | desc | varchar(64) | 否 | 描述 | |
4 | create_time | int(11) | 否 | 時間 |
重點關注type和Extra列spa
顯示這一行的數據是關於哪張表的orm
這是重要的列,顯示鏈接使用了何種類型,從最好到最差常常見到的type說明以下:排序
1,system索引
const類型的特列ci
2,consttable
表最多有一個匹配行,用於比較primary key或者unique索引
explain select * form pic where id=1
3,eq_ref
對於每一個來自於前面的表的行組合,從該表中讀取一行。這多是最好的聯接類型,除了const類型。它用在一個索引的全部部分被聯接使用而且索引是UNIQUE或PRIMARY KEY
explain select * from pic,user where pic.user_id = user.id
4,ref
鏈接不能基於關鍵字選擇單個行,可能查找到多個符合條件的行。叫作ref是由於索引要跟某個參考值相比較。這個參考值或者是一個常數,或者是來自一個表裏的多表查詢的結果值。
explain SELECT name FROM `user` WHERE name='1';
5,ref_or_null
如同ref,可是MySQL必須在初次查找的結果裏找出null條目,而後進行二次查找
以上五種是最優的
6,range
只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪一個索引。當使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操做符,用常量比較關鍵字列時,可使用range
7,index
全表掃描,只是掃描表的時候按照索引次序進行而不是行。主要優勢就是避免了排序,可是開銷仍然很是大。
explain SELECT name FROM `user` WHERE name=1
8,ALL
最壞的狀況,從頭至尾全表掃描
explain SELECT * FROM `user` WHERE name=1
顯示可能應用在這張表中的索引。若是爲空,沒有可能的索引,不過重要
MySQL實際從possible_key選擇使用的索引。若是爲NULL,則沒有使用索引。不多的狀況下,MYSQL會選擇優化不足的索引。這種狀況下,能夠在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引
使用的索引的長度。在不損失精確性的狀況下,長度越短越好
顯示索引的哪一列被使用了,若是可能的話,是一個常數
MYSQL認爲必須檢查的用來返回請求數據的行數
關於MYSQL如何解析查詢的額外信息。將在表4.3中討論,但這裏能夠看到的壞的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,結果是檢索會很慢
1,Distinct
一旦MYSQL找到了與行相聯合匹配的行,中止爲當前的行組合搜索更多的行
2,Not exists
MYSQL優化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行,就再也不搜索了
3,Range checked for each Record(index map:#)
沒有找到理想的索引,所以對於從前面表中來的每個行組合,MYSQL檢查使用哪一個索引,並用它來從表中返回行。這是使用索引的最慢的鏈接之一
4,Using filesort
看到這個的時候,查詢就須要優化了。不是「使用文件索引」的含義!filesort是MySQL所實現的一種排序策略,一般在使用到排序語句ORDER BY的時候,會出現該信息。
5,Using index
僅僅使用了索引中的信息而沒有讀取實際的行動的表返回的,這發生在對錶的所有的請求列都是同一個索引的部分的時候。若是隻有 Using index,說明他沒有查詢到數據表,只用索引表就完成了這個查詢,這個叫覆蓋索引。若是同時出現Using where,表明使用索引來查找讀取記錄, 也是能夠用到索引的,可是須要查詢到數據表。
6,Using temporary
看到這個的時候,查詢須要優化了。這裏,MYSQL須要建立一個臨時表來存儲結果,這一般發生在對不一樣的列集進行ORDER BY上,而不是GROUP BY上Where used 使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給用戶。若是不想返回表中的所有行,而且鏈接類型ALL或index,這就會發生,或者是查詢有問題不一樣鏈接類型的解釋(按照效率高低的順序排序)
7,using where
表示條件查詢,若是不讀取表的全部數據,或不是僅僅經過索引就能夠獲取全部須要的數據,則會出現 Using where。若是type列是ALL或index,而沒有出現該信息,則你有可能在執行錯誤的查詢:返回全部數據。
若是EXPLAIN出現後面兩個信息(Using filesort,Using temporary),而rows又比較大,一般意味着你須要調整查詢語句,或者須要添加索引,總之須要儘可能消除這兩個信息。