【整理】explain、type、extra用法和結果的含義


EXPLAIN列詳情

詳細解讀:https://www.cnblogs.com/yycc/p/7338894.html

 

explain顯示了mysql如何使用索引來處理select語句以及連接表。可以幫助選擇更好的索引和寫出更優化的查詢語句。

 

使用方法,在select語句前加上explain就可以了:

 

如:explain select surname,first_name form a,b where a.id=b.id 

 

table:顯示這一行的數據是關於哪張表的

type:這是重要的列,顯示連接使用了何種類型。從最好到最差的連接類型為const、eq_reg、ref、range、indexhe和ALL

possible_keys:顯示可能應用在這張表中的索引。如果為空,沒有可能的索引。可以為相關的域從WHERE語句中選擇一個合適的語句

key: 實際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MYSQL會選擇優化不足的索引。這種情況下,可以在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引

key_len:使用的索引的長度。在不損失精確性的情況下,長度越短越好

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

rows:MYSQL認為必須檢查的用來返回請求數據的行數

Extra:關於MYSQL如何解析查詢的額外信息。將在表4.3中討論,但這里可以看到的壞的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,結果是檢索會很慢,詳見下面解釋。

Type列詳解

Type:告訴我們對表使用的訪問方式,主要包含如下集中類型。

all:全表掃描。

const:讀常量,最多只會有一條記錄匹配,由於是常量,實際上只須要讀一次。

eq_ref:最多只會有一條匹配結果,一般是通過主鍵或唯一鍵索引來訪問。

fulltext:進行全文索引檢索。

index:全索引掃描。

index_merge:查詢中同時使用兩個(或更多)索引,然后對索引結果進行合並(merge),再讀取表數據。

index_subquery:子查詢中的返回結果字段組合是一個索引(或索引組合),但不是一個主鍵或唯一索引。

rang:索引范圍掃描。

ref:Join語句中被驅動表索引引用的查詢。

ref_or_null:與ref的唯一區別就是在使用索引引用的查詢之外再增加一個空值的查詢。

system:系統表,表中只有一行數據;

unique_subquery:子查詢中的返回結果字段組合是主鍵或唯一約束。

Extra字段解釋

Extra:查詢中每一步實現的額外細節信息,主要會是以下內容。

Distinct:查找distinct 值,當mysql找到了第一條匹配的結果時,將停止該值的查詢,轉為后面其他值查詢。

Full scan on NULL key:子查詢中的一種優化方式,主要在遇到無法通過索引訪問null值的使用。

Range checked for each record (index map: N):通過 MySQL 官方手冊的描述,當 MySQL Query Optimizer 沒有發現好的可以使用的索引時,如果發現前面表的列值已知,部分索引可以使用。對前面表的每個行組合,MySQL檢查是否可以使用range或 index_merge訪問方法來索取行。

SELECT tables optimized away:當我們使用某些聚合函數來訪問存在索引的某個字段時,MySQL Query Optimizer 會通過索引直接一次定位到所需的數據行完成整個查詢。當然,前提是在 Query 中不能有 GROUP BY 操作。如使用MIN()或MAX()的時候。

Using filesort:當Query 中包含 ORDER BY 操作,而且無法利用索引完成排序操作的時候,MySQL Query Optimizer 不得不選擇相應的排序算法來實現。

Using index:所需數據只需在 Index 即可全部獲得,不須要再到表中取數據。

Using index for group-by:數據訪問和 Using index 一樣,所需數據只須要讀取索引,當Query 中使用GROUP BY或DISTINCT 子句時,如果分組字段也在索引中,Extra中的信息就會是 Using index for group-by。

Using temporary:當 MySQL 在某些操作中必須使用臨時表時,在 Extra 信息中就會出現Using temporary 。主要常見於 GROUP BY 和 ORDER BY 等操作中。

Using where:如果不讀取表的所有數據,或不是僅僅通過索引就可以獲取所有需要的數據,則會出現 Using where 信息。

Using where with pushed condition:這是一個僅僅在 NDBCluster存儲引擎中才會出現的信息,而且還須要通過打開 Condition Pushdown 優化功能才可能被使用。控制參數為 engine_condition_pushdown 。

Impossible WHERE noticed after reading const tables:MySQL Query Optimizer 通過收集到的統計信息判斷出不可能存在結果。

No tables:Query 語句中使用 FROM DUAL或不包含任何 FROM子句。

Not exists:在某些左連接中,MySQL Query Optimizer通過改變原有 Query 的組成而使用的優化方法,可以部分減少數據訪問次數。

Extra詳解

這個列可以顯示的信息非常多,有幾十種,常用的有:

distinct:在select部分使用了distinc關鍵字

no tables used:不帶from字句的查詢或者From dual查詢。 使用not in()形式子查詢或not exists運算符的連接查詢,這種叫做反連接。即,一般連接查詢是先查詢內表,再查詢外表,反連接就是先查詢外表,再查詢內表。

using filesort:排序時無法使用到索引時,就會出現這個。常見於order by和group by語句中。

using index:查詢時不需要回表查詢,直接通過索引就可以獲取查詢的數據。

using_union:表示使用or連接各個使用索引的條件時,該信息表示從處理結果獲取並集

using intersect:表示使用and的各個索引的條件時,該信息表示是從處理結果獲取交集

using sort_union和using sort_intersection:與前面兩個對應的類似,只是他們是出現在用and和or查詢信息量大時,先查詢主鍵,然后進行排序合並后,才能讀取記錄並返回。

using where:表示存儲引擎返回的記錄並不是所有的都滿足查詢條件,需要在server層進行過濾。查詢條件中分為限制條件和檢查條件,5.6之前,存儲引擎只能根據限制條件掃描數據並返回,然后server層根據檢查條件進行過濾再返回真正符合查詢的數據。5.6.x之后支持ICP特性,可以把檢查條件也下推到存儲引擎層,不符合檢查條件和限制條件的數據,直接不讀取,這樣就大大減少了存儲引擎掃描的記錄數量。extra列顯示using index condition

using temporary:表示使用了臨時表存儲中間結果。臨時表可以是內存臨時表和磁盤臨時表,執行計划中看不出來,需要查看status變量,used_tmp_table,used_tmp_disk_table才能看出來。

firstmatch(tb_name):5.6.x開始引入的優化子查詢的新特性之一,常見於where字句含有in()類型的子查詢。如果內表的數據量比較大,就可能出現這個

loosescan(m..n):5.6.x之后引入的優化子查詢的新特性之一,在in()類型的子查詢中,子查詢返回的可能有重復記錄時,就可能出現這個

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

MySQL高級命令

  1. 強制索引MySQL FORCE INDEX

SELECT * FROM TABLE1 FORCE INDEX (FIELD1)

以上的SQL語句只使用建立在FIELD1上的索引,而不使用其它字段上的索引。

  1. 忽略索引 IGNORE INDEX

SELECT * FROM TABLE1 IGNORE INDEX (FIELD1, FIELD2)

在上面的SQL語句中,TABLE1表中FIELD1和FIELD2上的索引不被使用。

  1. 關閉查詢緩沖 SQL_NO_CACHE

SELECT SQL_NO_CACHE field1, field2 FROM TABLE1;

有一些SQL語句需要實時地查詢數據,或者並不經常使用(可能一天就執行一兩次),這樣就需要把緩沖關了,不管這條SQL語句是否被執行過,服務器都不會在緩沖區中查找,每次都會執行它。

  1. MySQL force Index 強制索引:強制查詢緩沖 SQL_CACHE

SELECT SQL_CALHE * FROM TABLE1;

如果在my.ini中的query_cache_type設成2,這樣只有在使用了SQL_CACHE后,才使用查詢緩沖。

  1. 優先操作 HIGH_PRIORITY

SELECT HIGH_PRIORITY * FROM TABLE1;

HIGH_PRIORITY可以使用在select和insert操作中,讓MySQL知道,這個操作優先進行。

  1. 滯后操作 LOW_PRIORITY

update LOW_PRIORITY table1 set field1= where field1=

LOW_PRIORITY可以使用在insert和update操作中,讓MySQL知道,這個操作滯后。

  1. 延時插入 INSERT DELAYED

INSERT DELAYED INTO table1 set field1=

INSERT DELAYED INTO,是客戶端提交數據給MySQL,MySQL返回OK狀態給客戶端。而這是並不是已經將數據插入表,而是存儲在內存里面等待排隊。當MySQL有空余時,再插入。另一個重要的好處是,來自許多客戶端的插入被集中在一起,並被編寫入一個塊。這比執行許多獨立的插入要快很多。壞處是,不能返回自動遞增的ID,以及系統崩潰時,MySQL還沒有來得及插入數據的話,這些數據將會丟失。

  1. 強制連接順序 STRAIGHT_JOIN

SELECT TABLE1.FIELD1, TABLE2.FIELD2 FROM TABLE1 STRAIGHT_JOIN TABLE2 WHERE

由上面的SQL語句可知,通過STRAIGHT_JOIN強迫MySQL按TABLE1、TABLE2的順序連接表。如果你認為按自己的順序比MySQL推薦的順序進行連接的效率高的話,就可以通過STRAIGHT_JOIN來確定連接順序。

  1. MySQL force Index 強制索引:強制使用臨時表 SQL_BUFFER_RESULT

SELECT SQL_BUFFER_RESULT * FROM TABLE1 WHERE

當我們查詢的結果集中的數據比較多時,可以通過SQL_BUFFER_RESULT.選項強制將結果集放到臨時表中,這樣就可以很快地釋放MySQL的表鎖(這樣其它的SQL語句就可以對這些記錄進行查詢了),並且可以長時間地為客戶端提供大記錄集。

  1. 分組使用臨時表 SQL_BIG_RESULT和SQL_SMALL_RESULT

SELECT SQL_BUFFER_RESULT FIELD1, COUNT(*) FROM TABLE1 GROUP BY FIELD1;

一般用於分組或DISTINCT關鍵字,這個選項通知MySQL,如果有必要,就將查詢結果放到臨時表中,甚至在臨時表中進行排序。SQL_SMALL_RESULT比起SQL_BIG_RESULT差不多,很少使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM