MySQL性能優化(四)--Explain執行計劃與show Profile分析

  MySQL的Explain執行計劃可以用來對Sql語句進行分析,是否進行全表掃描,是否用了索引,或者是sql語句先後執行計劃,有沒有用臨時表等等,由此來進行Sql優化,而show Profile和Explain一樣都是用來查看Sql語句分析的,但是形式不一樣,show Profile用來分析當前會話語句執行的資源消耗情況,能清晰的知道sql執行過程,以及過程中消耗的時間。

那麼咱們先來說一下Explain執行計劃

這是執行Explain命令後顯示的信息,那麼不熟悉的就會對此比較陌生,下面來一一講解每個列的說明。

1.Explain各字段含義

1.1 id列

id列的編號是select的序列號,表示查詢中執行select子句或操作表的順序

id序列數不同,如果是子查詢的話,則id值越大優先級越高,越先被執行

id序列數相同,則執行順序由上到下

id既有相同又有不同的,視爲相同的一組,執行順序由上到下,不同的id序列數越大,優先值越高

1.2 select_type列

select_type是查詢類型,說明查詢的種類

1.SIMPLE:簡單查詢,查詢不包含子查詢和UNION。

2.PRIMARY:複雜查詢包含含子部分,最外層查詢則被標記爲PRIMARY

3.DERIVED(form型子查詢):包含在from子句中的子查詢。MySQL會將結果存放在一個臨時表中,也稱爲派生表.

4.UNION:在UNION中第二個隨後的select

5.UNION RESULT:從UNION臨時表檢索結果的select(如果無需要儘量少寫union,因爲使用的是臨時表,所以不能進行索引優化)

6.DEPENDENT UNION:UNION語句中的第二個SELECT,依賴於外部子查詢  (暫時沒有寫到出現DEPENDENT UNION的sql所以沒有示例)

7.SUBQUERY(非form子查詢):包含在select中的子查詢。

8.DEPENDENT SUBQUERY:子查詢中的第一個SELECT,取決於外面的子查詢

1.3 table列

指的就是當前執行的表

1.4 partitions列

分區表

1.5 type列

type所顯示的是查詢使用了哪種類型,即MySQL決定如何查找表中的行。以下是按執行效率排序,優化最好是能優化最高的。

1.system:表只有一行記錄(等於系統表),這是const類型的特例,平時不會出現,這個也可以忽略不計。標紅的常用經常出現的

2.const:MySQL能對查詢的某部分進行優化並將其轉化爲一個常量,const 用於比較primary key 或者unique索引。因爲只匹配一行數據所以很快,一般用於主鍵刷選

3.eq_ref:primary key 或 unique key 索引的所有部分被連接使用,最多隻會返回符合條件的記錄,這可能是const之外最好的連接類型了,簡單的select查詢不會出現這種type(一般用於關聯查詢),唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描

4.ref:相比eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前綴,索引要和某個值相比較,可能會找到多個符合條件的行(非主鍵非唯一性索引的數據檢索)非唯一性索引掃描,返回匹配某個單獨值的所有行,本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,所以他應該屬於查找和掃描的混合體。

5.fulltex:

6.ref_or_null:類似ref,但是可以搜索值爲null的行

示例: 運行explain select * from film where name = "film1" or name is null;

7.index_merge:多重範圍掃描,兩表連接的每個表的連接字段上均有索引存在且索引有序,結果合併在一起,適用於做集合的並、交操作。

8.unique_subquery:在子查詢中基於唯一索引進行掃描,類似於eq_ref

9.index_ subquery:在子查詢中基於除唯一索引之外的索引進行掃描

10.range只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪個索引,一般在where語句中會出現between,>,<,in等查詢,這種範圍掃描索引比全表掃描好,因爲它只需要開始於索引的某一個點,而結束於另一點,不用掃描全部索引。Range性能飄忽不定的,主要是看範圍給定的多少,數值大,掃描多,數值小,掃描小(範圍檢索)

11.index:index是基於索引樹進行全表掃描,所以通常比ALL快,因爲索引文件通常比數據文件小。index是從索引中讀取多的,all是從硬盤中讀取的

12.ALL:全表掃描,意味着mysql從頭到尾去查找所需要的行。通常情況下需要增加索引來進行優化了。不使用索引,順序掃描,直接讀取表上的數據(訪問數據文件)

示例: 運行explain select * from actor;

13.INDEX_SCAN: 索引做掃描,是基於索引在索引的葉子節點上找滿足條件的數據(不需要訪問數據文件)

1.6 possible_key列

這一列顯示查詢可能使用哪些索引來查找(備選項),不是實際使用的。

1.7 key列

這一列顯示mysql實際採用哪個索引來優化對該表的訪問。

1.8 key_len列

這一行顯示了MySQL在索引(key)裏使用的字節數,可通過該列計算查詢中使用的索引的長度,在不損失精確性的情況下,長度越短越好,key_len顯示的值爲索引字段的最大可能長度,並非實際使用長度,即key_len是根據表定義計算而得,不是通過表內檢索出的

1.9 ref列

這一列顯示了在key列記錄的索引中,表查找值所用到的列或常量,常見的有:const(常量),func,NULL,字段名(例:film.id

通過type知道主外鍵關係,通過key主鍵索引知道ref的哪個表關聯,也知道哪個字段與之關聯對應

1.10 rows列

根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數,也就是說,用的越少越好

1.11 filtered列

是一個百分比的值,代表(rows * filtered)/100,這個結果將於前表產生交互

1.12 Extra列

這一列展示的是除解釋語句以外的額外信息,也是十分重要的信息

1.distinct:優化distinct操作,在找到第一匹配的元素後即停止找同樣值的動作。

2.Using index(效率很好):表示相應的select操作中使用了覆蓋索引(Covering index),避免訪問了表的數據行,是性能高的表現,如果同時出現using where,表明索引被用來執行索引鍵值的查找;如果沒有同時出現using where,表明索引用來讀取數據而非執行查找動作。

同時出現Using Where 表明索引被用來執行索引鍵值的查找

沒有同是出現Using where 表明索引用來讀取數據而非執行查找動作

引申一下,覆蓋索引在我的博客 MySQL性能優化(三)--MySQL索引詳細介紹(乾貨滿滿)有講到,在這裏放一個小小的鏈接 

https://blog.csdn.net/dfBeautifulLive/article/details/103202803

3.Using where:MySQL服務器將在存儲引擎檢索行後再進行過濾,就是先讀取整行數據,再按where條件進行檢查,符合就留下,不符合就丟棄。

4.Using filesort(效率很差):MySQL會對數據使用一個外部的索引排序,而不是按照表內的索引順序進行讀取,MySQL中無法利用索引完成的排序操作稱爲"文件排序"

5.Using temporary(效率更差):使用了臨時表保存中間結果,出現這種情況一般都需要進行優化,MySQL在對查詢結果排序時使用臨時表。常見於排序order by和分組查詢group by。

6.Using join buffer:表明使用了連接緩存,比如說在查詢的時候多表join的次數非常多,那麼將配置文件中的緩衝區的join buffer調大一些。

7.impossible where:where子句的值總是false,不能用來獲取任何元素

2.show Profile SQL分析

SHOW PROFILE 是MySQL提供可以用來分析當前會話語句執行的資源消耗情況,可以用於SQL 的調優測評依據,

SHOW VARIABLES LIKE 'PROFILING'通過這個命令查看參數開關情況

如果是關閉的可以通過這個命令設置開啓SET PROFILING = ON;

也可以通過select @@have_profiling命令查看MySQL是否支持profile

如果是profiling是關閉的,通過Set語句開啓 set profiling=1;

通過show profiles 查詢最近15次運行結果

比如我查詢這個sql語句,select count(*) from registered_kj_resourcegroup_type,查詢完畢執行show profiles命令,那麼咱們剛纔執行的sql情況就出來了

Query_ID屬性:表示從連接上數據庫到現在執行的SQL 語句序號

Duration屬性:表示執行該SQL 所耗費的時間(S)

Query屬性:表示執行的操作

通過show profile for query 285語句能夠看到執行過程中線程的每個狀態和消耗的時間:

注意: Sending data狀態表示MySQL線程開始訪問數據行並把結果返回給客戶端,而不僅僅是返回結果給客戶端。

           由於在Sending data狀態下,MySQL線程往往需要做大量的磁盤讀取操作,所以經常是整個查詢中耗時最長的狀態。

如果對MySQL源碼感興趣可以通過show profile source for query查看SQL解析執行過程中每個步驟對應的源碼文件、函數名以及具體的源文件行數。

如命令:show profile source for query 310

Source_function屬性:函數名稱

Source_file屬性:源文件

Source_line屬性:源文件行數

 

 

 

 

 

 

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