本文從以下幾方面對MySQL優化進行分析
- 獲取有性能問題的SQL
- 通過慢查詢日誌獲取有性能問題的SQL
- 慢查詢日誌內容
- 實時獲取有性能問題的SQL
- SQL預處理解析
- 如何確定查詢消耗時間
- 優化特定的SQL
一丶獲取有性能問題的SQL
- 通過用戶反饋獲取存在問題的SQL,此用戶一般爲測試人員,例執行某一個查詢非常慢(不推薦)
- 通過慢查詢日誌獲取存在性能問題的SQL
- 實時獲取存在性能問題的SQL
以下着重介紹上述2,3點
二丶通過慢查詢日誌獲取有性能問題的SQL
相關參數:
① 啓動/停止記錄慢查詢日誌
set global slow_query_log = on/off # 還可以通過其他方式定時開關閉
② 指定慢查詢的存儲路徑及文件名
slow_query_log_file #默認保存在mysql的數據目錄中
③ 指定記錄慢查詢日誌SQL執行時間的閾值,以秒爲單位
long_query_time
其中MySQL慢查詢日誌記錄的包括:查詢語句,數據修改語句,事務回滾的SQL。慢查詢默認時間爲10s,通常修改爲1毫秒
④ 是否記錄未使用索引的SQL
log_queries_not_using_innndexes
三丶兩種方式分析慢查詢日誌內容
#user@Host:sbtest[sbtest]@localhost[] Id:7
#Query_time:0.000233
#lock_time:0.000120
#Rows_sent:1 #掃描的數據行數
#Rows_examined:1 #返回的數據行數
SET timestamp = 1458612917 #SQL執行時間
select id from sbtest where id = 1; #執行的SQL
⑴ 常用的慢查詢分析工具1
mysqldumpslow : 彙總除查詢條件外其他完全相同的SQL,並將分析結果按照參數中所指定的順序輸出
命令:
mysqldumpslow -s r -t 10 slow -mysql.log
#-t 表示 按總時間。還有以下幾個參數,c:總次數。t:總時間。l:鎖的時間。r:總數據行。at,al,ar:表示t,l,r的平均數
⑵ 常用的慢查詢分析工具2
pt-query-digest : 使用慢查詢日誌獲取有性能問題的SQL並生成查詢報告
命令:
pt-query-digest \
--explain h=127.0.0.1,u=username,p=password \
slow -mysql.log
四丶實時獲取有性能問題的SQL
利用MySQL下 information_schema 庫下的 processlist 表,實時獲取有問題的SQL
五丶SQL解析預處理
MySQL執行查詢語句的流程爲:客服端發送SQL請求,SQL服務器判斷是否命中緩存,MySQL進行SQL解析預處理,優化器生成對應的執行計劃,根據執行計劃調用API查詢數據,最後將結果返回給客戶端。
⑴ 打開查詢緩存(對於一個讀寫頻繁的系統使用查詢緩存很可能會降低查詢處理效率)
query_cache_type #設置緩存是否開啓或關閉
query_cache_size #設置查詢緩存的內存大小
query_cache_limit #設置查詢緩存可用的存儲最大值
query_cache_wlock_invalidate #設置數據表被鎖後是否返回緩存中的數據
query_cache_min_res_unit #設置查詢緩存分配的內存最小單位
⑵ SQL預處理階段
檢查SQL語法是否正確並生成查詢計劃
MySQL生成錯誤的查詢計劃可能的原因:
① 統計信息不準確
② 查詢計劃中的成本估算不等同於實際計劃成本
③ MySQL優化器認爲的最後與實際存在一定偏差
造成以上的原因可能爲:
① MySQL不考慮其他併發查詢
② MySQL的既定規則
③ 調用了MySQL存儲過程及用戶自定的函數
比如執行了一條錯誤的SQL,select id from a where id = -1;
⑶ 查詢優化器支持的SQL
① 重新定義表的關聯順序
② 將外連接轉化成內連接
③ 使用等價變化規則 如 where id.>5 and id =5 轉換爲 where id>=5
③ 優化 count(id) min(id) max(id) 統計行的最大最小值等
④ 將一個表達式轉換爲常數,比如在求某一個時間字段時,不用系統函數而採用給定的固定值
⑤ 子查詢優化,可以將子查詢轉化爲關聯查詢
⑥ 對 not in , <>等的優化
六丶兩種方式確定查詢消耗時間
⑴ profile (mysql5.5以前版本)
set profile = 1; #啓動profile
###執行查詢語句
show profiles; #查看每一個查詢語句消耗的總的時間信息
show profile for query query_id #查詢某個query_id在每個階段消耗的時間
show profile cpu query query_id #查詢某個query_id在每個階段消耗的CPU信息
⑵ performance_schema(mysql5.5以後版本)
① 啓動proformance_schema
② 查看其它線程所消耗的時間
七丶舉例優化特定的SQL
⑴ 在千萬級的表中刪除或修改百萬行數據(分批次修改,並單次修改完間隔幾秒再執行操作)
⑵ 對大表的結構進行修改
⑶ 優化 not in , <>查詢 ,例:
原SQL:
select aid from a where aid not in (select aid from b)
優化後SQL:
select aid from a aa left join b bb on aa.aid = bb.bid where bb.bid IS NULL
⑷ 優化主鍵最左匹配
例:
原:select aid from a where addtime > '2018-07-22' and aid >10;
優:select aid from a where aid > 10 and addtime > '2018-07-22';
(5) 隨機獲取數據
原:
SELECT * FROM `tabName` ORDER BY rand() LIMIT 5 #大表此語句會存在性能問題
優化:
SELECT * FROM `tabName` WHERE id>= (SELECT floor(RAND() * ((SELECT MAX(id) FROM `tabName`) - (SELECT MIN(id) FROM `tabName`)) + (SELECT MIN(id) FROM `tabName`))) ORDER BY idLIMIT 5 #優化後能毫秒級響應