淺談MySQL查詢優化

 

本文從以下幾方面對MySQL優化進行分析

  • 獲取有性能問題的SQL
  • 通過慢查詢日誌獲取有性能問題的SQL
  • 慢查詢日誌內容
  • 實時獲取有性能問題的SQL
  • SQL預處理解析
  • 如何確定查詢消耗時間
  • 優化特定的SQL

一丶獲取有性能問題的SQL

  1. 通過用戶反饋獲取存在問題的SQL,此用戶一般爲測試人員,例執行某一個查詢非常慢(不推薦)
  2. 通過慢查詢日誌獲取存在性能問題的SQL
  3. 實時獲取存在性能問題的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 #優化後能毫秒級響應

  

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