【MySQL優化】1、定位問題
後端開發離不開與資料庫打交道, 資料庫種類也很多,接觸過的有MySQL、Oracle、HBase、Redis等,此文中優化的主要針對MySQL,並結合開發中經常遇到的場景,參考網上資料和相關書籍,將優化記錄總結。
下圖是根據現階段理解整理的腦圖,後期也會在此基礎上補充或修改。
由於篇幅較長,故分開記錄,此文主要詳細說明MySQL優化之定位問題
。
定位問題
通過show status 命令瞭解各種SQL的執行頻率
SHOW STATUS LIKE 'Com_%';
執行結果如下:
Com_xxx 表示每個xxx語句執行的次數,我們通常比較關心的是一下幾個統計引數。
- Com_select:執行SELECT操作的次數,一次查詢只累加1;
- Com_insert:執行INSERT操作的次數,對於批量插入的INSERT操作,只累加一次;
- Com_update:執行UPDATE操作的次數;
- Com_delete:執行DELETE操作的次數;
此外,以下幾個引數便於使用者瞭解資料庫的基本情況: - Connection:試圖連線MySQL伺服器的次數;
- Uptime:伺服器工作時間;
- Slow_queries:慢查詢的次數。
定位執行效率低的SQL語句
可以通過以下兩種方式定位執行效率低得SQL語句:
- 通過慢查詢日誌定位那些查詢效率較低的SQL語句,使用–slow_query_log[={0|1}]顯式指定慢查詢的狀態,如果不指定值或者指定值為1都會開啟慢查詢;使用slow_query_log_file[=file_name]來指定慢查詢日誌的路徑;
- 慢查詢日誌在查詢結束後才記錄,所以在應用反映執行效率出現問題的時候查詢慢查詢日誌並不能定位問題,可以使用show processlist命令檢視當前MySQL在進行的執行緒,包括執行緒的狀態、是否鎖表等,可以實時地檢視SQL的執行情況,同時對一些鎖表操作進行優化。
通過EXPLAIN分析低效SQL的執行計劃
通過以上步驟查詢到效率低的SQL語句後,可以通過EXPLAIN或者DESC命令獲取MySQL如何執行SELECT語句的資訊,包括在SELECT語句執行過程中表如何連線和連線的順序。
對每個列簡單進行說明:
- select_type:表示SELECT的型別,常見取值有SIMPLE(簡單表,即不使用表連線或者子查詢)、PRIMARY(主查詢,即外層的查詢)、UNION(UNION中的第二個或者後面的查詢語句)、SUBQUERY(子查詢中的第一個SELECT)等。
- table:輸出結果集的表。
- type:表示MySQL在表中找到所需行的方式,或者叫訪問型別,常見型別(1到7型別依次變差):
(1)type=ALL,全表掃描,MySQL遍歷全表來找到匹配的行;
(2)type=index,索引全掃描,MySQL遍歷整個索引來查詢匹配的行;
(3)type=range,索引範圍掃描,常見於<、<=、>、>=、between等操作符;
(4)type=ref,使用非唯一索引的字首掃描,返回匹配某個單獨值得記錄行;
(5)type=eq_ref,類似ref,區別就在使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配,簡單的說,就是多表連線中使用primary key或者unique index作為關聯條件;
(6)type=const/system,單表中最多有一個匹配行,例如,根據主鍵primary key或者唯一索引unique index進行查詢;
(7)type=NULL,MySQL不用訪問表或者索引,直接就能得到結果。 - possible_keys:表示查詢時可能使用的索引。
- key:表示實際使用的索引。
- key-len:使用到索引欄位的長度。
- rows:掃描行的數量。
- Extra:執行情況的說明和描述,包括不適合在其他列中顯示但是對執行計劃非常重要的額外資訊。
有的時候,僅僅通過explain分析執行計劃並不能很快的定位SQL的問題,這個時候我們還可以選擇profile聯合分析。
通過show profile分析SQL
MySQL從5.0.37版本開始增加了對show profiles和show profile語句的支援。通過have_profiling引數能看出當前MySQL是否支援profile:
根據書中(《深入淺出MySQL》)實踐,並未出現理想效果:
直接使用Navicat Premium 12
視覺化工具就有profile資訊了:
通過trace分析優化器如何選擇執行計劃
MySQL5.6提供了對SQL的跟蹤trace,通過trace檔案能夠進一步瞭解優化器的行為。
使用方式:首先開啟trace,設定格式為JSON,設定trace最大能夠使用的記憶體大小,便面解析過程中因為預設記憶體過小而不能夠完整顯示。
SET OPTIMIZER_TRACE="enabled=on",END_MARKERS_IN_JSON=on;
SET OPTIMIZER_TRACE_MAX_MEM_SIZE=1000000;
確定問題並採取相應的優化措施
經過以上步驟,基本確認出現的原因。
可以通過建立索引,修改欄位屬性,修改查詢語句等方式進行優化,後面文章中將會一一講解。