【mysql】分析mysql執行計劃

使用EXPLAIN優化查詢

EXPLAIN後可接 SELECT, DELETE, INSERT, REPLACE,和 UPDATE語句。如下:

explain 
select DISTINCT r.STAFF_IDS, d.SPLITLIST_ID, d.SPLITLIST_NAME, d.LIST_ID, d.OWNED_CITY, d.OWNED_CHANNEL, d.STORAGE_PATH, d.REMARK, m.PUBLISHER_TIME, m.EXP_TIME, m.LIST_STATUS, o.DOWNLOAD_STATUS, m.CATEGORY, m.LIST_ID, m.belong_date 
from rpt_list m 
left join rpt_split_list d on d.LIST_ID = m.LIST_ID 
left join rpt_list_staff_rel r ON d.SPLITLIST_ID=r.list_id 
left join rpt_listexp_log o on d.SPLITLIST_ID = o.SPLITLIST_ID 
WHERE m.LIST_STATUS = '5' 
and ((m.category in ('jkqd', 'scbqd', 'zqkhb', 'cljy', '2to4') and r.staff_ids IS NULL  
and d.OWNED_CITY in ('瀋陽','48元檔位') ) 
or (r.STAFF_IDS in ( '822') and m.category in ('staff'))) 
order by publisher_time desc limit 0 , 10 ;

查詢結果如下:
執行計劃結果

EXPLAIN輸出格式

EXPLAIN輸出列

JSON名稱 含義
id select_id 該SELECT標識符
select_type 沒有 該SELECT類型
table table_name 輸出行的表
partitions partitions 匹配的分區
type access_type 連接類型
possible_keys possible_keys 可供選擇的索引
key key 實際選擇的指數
key_len key_length 所選鍵的長度
ref ref 列與索引進行比較
rows rows 估計要檢查的行
filtered filtered 按表條件過濾的行的百分比
Extra 沒有 附加信息

id

包含一組數字,表示查詢中執行select子句或操作表的順序
id相同,執行順序由上至下,否則id值越大(通常子查詢會產生)優先級越高,越先被執行
id如果相同,可以認爲是一組,從上往下順序執行;在所有組中,id值越大,優先級越高,越先執行

select_type

select_type值 含義
SIMPLE 簡單SELECT(不使用 UNION或子查詢)
PRIMARY Outermost SELECT 最外層select
UNION Second or later SELECT statement in a UNION
DEPENDENT UNION Second or later SELECT statement in a UNION, dependent on outer query
UNION RESULT Result of a UNION.
SUBQUERY First SELECT in subquery
DEPENDENT SUBQUERY First SELECT in subquery, dependent on outer query(通常爲相關子查詢)
DERIVED 派生表 Derived table SELECT (subquery in FROM clause)
MATERIALIZED 物化子查詢 Materialized subquery
UNCACHEABLE SUBQUERY 無法緩存結果的子查詢,必須爲外部查詢的每一行重新計算 A subquery for which the result cannot be cached and must be reevaluated
UNCACHEABLE UNION for each row of the outer query

table

輸出行引用的表的名稱。

partitions

查詢將匹配記錄的分區。僅當使用PARTITIONS關鍵字時,纔會顯示此列 。該值適用NULL於非分區表。

type

連接類型。以下列表描述了從最佳類型到最差類型的連接類型:

system

該表只有一行(=系統表)。這是const連接類型的特例 。

const

該表最多隻有一個匹配行,在查詢開頭讀取。因爲只有一行,所以優化器的其餘部分可以將此行中列的值視爲常量。 const表非常快,因爲它們只讀一次。

const將a PRIMARY KEY或 UNIQUE索引的所有部分與常量值進行比較時使用。在以下查詢中,tbl_name可以用作const 表:

eq_ref

對於前面表格中的每個行組合,從該表中讀取一行。除了 system和 const類型之外,這是最好的連接類型。當連接使用索引的所有部分且索引是 索引PRIMARY KEY或UNIQUE NOT NULL索引時使用它。

eq_ref可用於使用=運算符進行比較的索引列 。比較值可以是常量,也可以是使用在此表之前讀取的表中的列的表達式。

ref

對於前面表中的每個行組合,將從此表中讀取具有匹配索引值的所有行。ref如果連接僅使用鍵的最左前綴或者鍵不是a PRIMARY KEY或 UNIQUE索引(換句話說,如果連接不能基於鍵值選擇單行),則使用此方法。如果使用的密鑰只匹配幾行,這是一個很好的連接類型。

ref可以用於使用=or <=> 運算符進行比較的索引列 。

fulltext

全文搜索

ref_or_null

這種連接類型是這樣的 ref,但除此之外,MySQL還會對包含NULL值的行進行額外搜索。此連接類型優化最常用於解析子查詢。

index_merge

此連接類型表示使用了索引合併優化。在這種情況下,key輸出行中的列包含使用的索引列表,並key_len包含所用索引 的最長關鍵部分的列表。有關更多信息,請參見 第8.2.1.3節“索引合併優化”。

unique_subquery

index_subquery

此連接類型類似於 unique_subquery。

range

僅檢索給定範圍內的行,使用索引選擇行。的key 輸出行中的列指示使用哪個索引。將key_len包含已使用的時間最長的關鍵部分。該ref列 NULL適用於此類型。

range當一個鍵柱使用任何的相比於恆定可使用 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, LIKE,或 IN()

index

該index聯接類型是一樣的 ALL,只是索引樹被掃描。這有兩種方式:

如果索引是查詢的覆蓋索引,並且可用於滿足表中所需的所有數據,則僅掃描索引樹。在這種情況下,Extra專欄說 Using index。僅索引掃描通常比ALL索引的大小通常小於表數據更快 。

使用索引中的讀取執行全表掃描,以按索引順序查找數據行。 Uses index沒有出現在 Extra列中。

當查詢僅使用屬於單個索引的列時,MySQL可以使用此連接類型。

ALL

對前面表格中的每個行組合進行全表掃描。如果表是第一個未標記的表 const,這通常是不好的,並且在所有其他情況下通常 非常糟糕。通常,您可以ALL通過添加索引來避免 ,這些索引根據以前表中的常量值或列值從表中啓用行檢索。

possible_keys

該possible_keys列指示MySQL可以從中選擇查找此表中的行的索引。請注意,此列完全獨立於輸出中顯示的表的順序 EXPLAIN。這意味着某些鍵possible_keys可能無法在生成中使用生成的表順序。

如果此列是NULL(或在JSON格式的輸出中未定義),則沒有相關索引。在這種情況下,您可以通過檢查WHERE 子句以檢查它是否引用適合索引的某些列或列來提高查詢性能。如果是,請創建適當的索引並EXPLAIN再次檢查查詢 。

要查看錶有哪些索引,請使用。 SHOW INDEX FROM tbl_name
優化建議

key

該key列指示MySQL實際決定使用的密鑰(索引)。如果MySQL決定使用其中一個possible_keys 索引來查找行,那麼該索引將被列爲鍵值。

可能key會命名值中不存在的索引 possible_keys。如果沒有possible_keys索引適合查找行,則會發生這種情況,但查詢選擇的所有列都是其他索引的列。也就是說,命名索引覆蓋了所選列,因此雖然它不用於確定要檢索的行,但索引掃描比數據行掃描更有效。

因爲InnoDB,即使查詢還選擇主鍵,輔助索引也可能覆蓋所選列,因爲InnoDB主鍵值與每個輔助索引一起存儲。如果 key是NULL,MySQL沒有找到用於更有效地執行查詢的索引。

要強制MySQL使用或忽略列出的索引 possible_keys列,使用 FORCE INDEX,USE INDEX或IGNORE INDEX在您的查詢。請參見第8.9.3節“索引提示”。

對於MyISAM和NDB 表,運行ANALYZE TABLE有助於優化器選擇更好的索引。對於NDB表,這還可以提高分佈式下推連接的性能。對於 MyISAM表格,myisamchk --analyze也是如此 ANALYZE TABLE。

key_len

該key_len列指示MySQL決定使用的密鑰的長度。該值 key_len使您可以確定MySQL實際使用的多部分密鑰的多少部分。如果key列說 NULL,該len_len 列也說NULL。

由於密鑰存儲格式,對於可能NULL 比列的列,密鑰長度更大NOT NULL。在不損失精確性的情況下,長度越短越好。

ref

該ref列顯示將哪些列或常量與列中指定的索引進行比較,以 key從表中選擇行。

如果值爲func,則使用的值是某個函數的結果。要查看哪個函數,請使用 SHOW WARNINGS以下內容 EXPLAIN EXTENDED查看擴展EXPLAIN輸出。該函數實際上可能是算術運算符等運算符。

rows

該rows列指示MySQL認爲必須檢查以執行查詢的行數。

對於InnoDB表格,此數字是估算值,可能並不總是準確的。

filtered

該filtered列指示將按表條件過濾的錶行的估計百分比。最大值爲100,這意味着不會對行進行過濾。值從100開始減少表示過濾量增加。 rows顯示檢查的估計行數,rows× filtered表示將與下表連接的行數。例如,如果 rows爲1000且 filtered爲50.00(50%),則使用下表連接的行數爲1000×50%= 500.如果使用,則顯示此列 EXPLAIN EXTENDED。

Extra

此列包含有關MySQL如何解析查詢的其他信息。

Using index condition

通過訪問索引元組並首先測試它們以確定是否讀取完整的錶行來讀取表。以這種方式,索引信息用於推遲(“ 下推 ”)讀取全錶行,除非有必要。
查詢優化器功能開關 SELECT @@optimizer_switch
默認情況下啓用索引條件下推。可以optimizer_switch通過設置index_condition_pushdown標誌來控制 系統變量 :
SET optimizer_switch = ‘index_condition_pushdown=off’;

Using where

使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給用戶。如果不想返回表中的全部行,並且連接類型ALL或index,這就會發生,或者是查詢有問題。

Using temporary

看到這個的時候,查詢需要優化了。這裏,mysql需要創建一個臨時表來存儲結果,這通常發生在對不同的列集進行ORDER BY上,而不是GROUP BY上。

Using filesort

看到這個的時候,查詢就需要優化了。mysql需要進行額外的步驟來發現如何對返回的行排序。它根據連接類型以及存儲排序鍵值和匹配條件的全部行的行指針來排序全部行。

Distinct

一旦mysql找到了與行相聯合匹配的行,就不再搜索了。

優化建議

  • 表關聯字段類型長度完全相同。
  • 將LEFT JOIN其更改爲內部聯接。
  • 查詢條件加索引條件,order by字段在group by中存在。

詳見:mysql官方解釋文檔

上一篇:【mycat】Linux下mycat搭建配置全過程——初學者輕鬆上手篇
下一篇:【R】linux上安裝R及使用shell調用加傳參

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