MySQL高級之第三天: 性能分析

今天主要是學習了MySQL的性能分析部分, 主要用到的關鍵字是explain, 它用於分析SQL語句的性能, 感覺今天滿滿的都是乾貨!!!

由於比較少人看我的博客, 我也不太在意你們是否會轉走我的博客或者抄襲什麼的, 總之希望你們都能夠有收穫!!!


MySQL性能分析

1. MySQL Query Optimizer

        MySQL有專門負責優化SELECT語句的優化器模塊.

        主要功能: 通過計算分析系統中收集到的統計信息, 爲客戶端請求的Query提供它認爲的最優執行計劃.

 

2. MySQL常見瓶頸:

1. CPU: CPU在飽和的時候一般發生在數據載入內存或從磁盤上讀取數據時候

2. IO: 磁盤I/O瓶頸發生在裝入數據遠大於內存容量的時候

3. 服務器硬件的性能瓶頸: top free iostat和vmstat來查看系統的性能狀態

 

3. 分析Sql語句的關鍵字Explain:

3.1 是什麼?

        查看執行計劃, 可以模擬優化器執行SQL查詢語句, 從而知道MySQL是如何處理程序員的SQL語句, 分析你的查詢語句或是表結構的性能瓶頸

3.2 能幹嘛?

1. 表的讀取順序(id)

2. 數據讀取操作的操作類型(select_type)

3. 哪些索引可以使用(possible_keys)

4. 哪些索引被實際使用(key)

5. 表之間的引用(ref)

6. 每張表有多少行被優化器查詢(rows)

3.3 怎麼玩?

1. Explain + SQL語句

2. 執行計劃包含的信息

id| select_type| table| type| possible_keys| key| key_len| ref| rows| Extra

3.4 各字段解釋

3.4.1 id(很重要):

select查詢的序列號,包含一組數字,表示查詢中執行select字句或操作表的順序

三種情況:

1. id相同, 執行順序由上到下

2. id全部不同, 如果是子查詢, id的序號會遞增, id的值越大優先級越高,越先被執行

3. id相同不同, 同時存在, 第2點和第1點的結合,id值越大優先級越高,越先被執行,id相同, 執行順序由上到下

3.4.2 select_type:

SIMPLE PRIMARY SUBQUERY DERIVED UNION (UNION RESULT)

SIMPLE:

簡單的select查詢, 查詢中不包含子查詢或者UNION

PRIMARY:

查詢中若包含任何複雜的子查詢,最外層查詢則被標記爲PRIMARY

SUBQUERY:

SELECT或WHERE列表中包含了子查詢

DERIVED:

FROM列表中包含的子查詢被標記爲DERIVED(衍生),MySQL會遞歸這些子查詢, 把結果放在臨時表中

UNION:

第二個SELECT出現在UNION之後, 則被標記爲UNION;若UNION包含在FROM子句的子查詢中, 外層SELECT被標記爲:DERIVED

UNION RESULT:

從UNION表獲取結果的SELECT

3.4.3 table:

這一行的數據是哪張表的

3.4.4 type(很重要):

顯示查詢使用了何種類型,

類型有如下:

ALL index range ref eq_ref const, system NULL

最好到最差依次是:

system>const>eq_ref>ref(常見)>range>index>ALL

一般來說,至少優化到ref.

system:

表只有一行記錄(等於系統表), 這是const類型的特列, 平時不會出現, 這個可以忽略不計

const:

索引一次就找到了, const用於比較primary key或者unique索引.

eq_ref:

唯一性索引掃描, 對於每個索引鍵, 表中只有一條記錄與之匹配.常見於主鍵

或稱爲唯一索引掃描

ref:(一般的SQL語句到達這一級,已經是相當好的了)

非唯一性索引掃描, 返回匹配某個單獨值的所有行.

例子 : 

explain SELECT * FROM photo ph  LEFT JOIN project pro ON pro.pro_name = ph.photo_type;

一個項目可以對應一張照片或者多張照片, 而對pro_name建立索引後, 會對某個項目的名字作爲索引去匹配圖片表中所有與該名字匹配的圖片的行.

只需關注紅框,其餘屬性在後面都會有說明.第一個紅框代表查詢了project表, 查詢類型爲ref, 可能使用到的索引是idx_proName, 實際使用到的也是idx_proName, 說明沒有發生索引失效問題(詳情可百度, 知識的海洋無邊無際哈哈哈哈哈~)

range:

只檢索給定範圍的行, 使用一個索引來選擇行, key列顯示使用了哪個索引

一般是在where語句中出現了between, <, >, in等的查詢

index:

Full Index Scan, 只遍歷索引樹, 比ALL快, 因爲索引文件通常比數據小,

index從索引裏找, ALL從硬盤中找, IO大.

ALL:

遍歷全表.

3.4.5 possible_keys:

顯示理論上應用在這張表的索引, 可能一個或多個

查詢涉及到的字段上若存在索引, 則該索引會被列出, 但不一定被查詢實際使用.

3.4.6 key(很重要):

顯示實際上使用到的索引, 如果爲NULL, 則沒有使用索引

查詢中若使用了覆蓋索引, 則該索引僅出現在key列表中

覆蓋索引是什麼?

select 後查詢的字段個數和順序與建立的複合索引個數和順序剛好吻合.

3.4.7 key_len:

顯示索引字段最大可能長度, 並非實際使用長度, 即key_len是根據表定義計算而得, 不是通過表內檢索出的.

在不損失精確度的情況下, 索引字段的長度越短越好

3.4.8 ref:

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

哪些列或常量被用於查找索引列上的值.

3.4.9 rows(很重要):

根據表統計信息及索引選用情況, 大致估算出所需記錄查詢的行數(查詢的越少越好)

3.4.10 Extra(很重要):

包含不適合在其他列顯示但十分重要的信息 :

1. Using filesort(很重要) :

九死一生!!!

說明MySQL會對數據使用一個外部的索引排序, 而不是按照表內的索引順序進行讀取.

MySQL無法利用索引完成的排序操作稱作"文件內排序".

若出現則代表SQL語句寫的爛, 執行速度會下降.

2. Using temporary(很重要):

十死無生!!!

使用了臨時表保存中間結果, 在查詢結果排序時使用臨時表. 大幅度影響執行性能

常見於排序order by和分組查詢group by

3. Using Index(很重要):

發財啦, 看到這個是好事!!!

表示響應的select操作使用了覆蓋索引(Covering Index), 避免訪問了表的數據行, 效率不錯!

如果同時出現using where, 表明索引被用來執行索引鍵值的查找;

如果沒有同時出現using where, 表明索引用來讀取數據而非執行查找動作

覆蓋索引(Covering Index):

select的數據列只用從索引中就可以取得, 不必讀取數據行, MySQL可以利用索引返回select列表中的字段, 而不必根據索引再次讀取數據文件, 換句話說, 查詢列要被所建的索引覆蓋.

 

Join語句的優化

儘可能減少Join語句中的NestedLoop的循環總次數; "永遠用小表驅動大表"

優先優化NestedLoop的內層循環

保證Join語句被驅動表上Join條件字段已經被索引;


結束語 : 希望我能夠給你們帶來一點小的幫助, 知識的坑是非常深的, 儘管跳下去吧!加油!!!

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