記一次MySQL性能優化

記一次MySQL性能優化

最近接到反饋,客戶端偶爾出現接口異常。經過初步的日誌排查發現是MySQL的問題,因而針對此次的異常對MySQL進行了一次性能問題追蹤和優化。事情搞定後就一直想寫一篇總結記錄下追蹤的過程以及優化的思路,最後在磨蹭了一個星期後有了這遍筆記。(筆記裏的數據表名和數據都爲過後在本地模擬,可能難以反映出線上當時的真實耗時狀況
首先說一下問題的情況:客戶端反應的情況是mysql間歇性鏈接超時。問題並不能明顯地反饋在某個sql上,經過查看監控日誌,發現內存間歇性飆升。
最開始懷疑是定時任務的問題,由於業務在後臺有不少定時任務,其中不乏對數據庫大量數據作聚合操做的任務,有一些任務在實現時沒有考慮其對性能的影響,每每會產生間歇性的數據庫性能不穩定。可是經過觀察發現此次內存飆升的時間間隔並不固定,初步排除是定時腳本的問題。
會不會是慢SQL的問題,因爲項目迭代開發速度的問題缺少很好的質量檢測,通常狀況下,這個問題是最常出現的性能問題,此次也不例外,第一時間將慢SQL日誌調出來查看。而後。。。嗯?此次的慢SQL有點多啊,而且有點繁雜,反應出來就是其中某個表  partner  ,跟這個表相關的sql所有被標記爲慢SQL。漸漸意識到問題有點嚴重呀!
而後隨便拿出一條慢SQL執行,嗯? 8ms,這是啥慢SQL,這已經要比數據庫的絕大多數哦SQL快了。索性在有一次問題復現時根據當時的 [show processlist]() 反饋,發現有會話數量很不穩定,忽高忽低,在內存飆升的延後幾秒中內每每會有大量的進程。在案發現場,定位到一個條可疑SQL,(根據進程的狀態、執行SQL的時間)。拿出來執行一下,發現確實是慢SQL,而後懷疑是當前內存不足的緣由致使的慢SQL,因而將這條SQL拿到寫數據庫中執行,發現依舊是很慢,因而定位到一個問題,具體是否是它致使了所有問題須要先優化了它再分析,保存了當時的processlist後對這條sql進行優化。
先來看一下這條SQL:select uid from partners where id in (1,2,3,"4","5",...) 
SQL的結構很簡單,就是根據id搜索partners表的uid,其中uid和id都有索引,id爲主鍵。問題SQL找到了下面就是SQL優化三板斧的工做了。
先進一步經過 profiles 來進一步定位問題。
mysql

Status Duration Block_ops_in Block_ops_out
starting 0.000046 0 0
checking permissions 0.000027 0 0
Opening tables 0.000049 0 0
init 0.000038 0 0
System lock 0.000027 0 0
optimizing 0.000028 0 0
statistics 0.000037 0 0
preparing 0.000030 0 0
executing 0.000025 0 0
Sending data 0.146700 64 1144
end 0.000077 0 0
query end 0.000027 0 0
closing tables 0.000031 0 0
freeing items 0.000049 0 0
cleaning up 0.000028 0 0

能夠很清楚的看到,語句在Sending data模塊消耗太多時間,而且進行了大量的IO操做。sending data表示收集+發送數據,一般產生的狀況有一下幾種:sql

  1. 存在大字段或返回數據量過大致使數據傳輸過慢。
  2. sql可能沒有走索引,掃了大量數據,從大量數據中找這一條記錄。
  3. 數據庫服務器網絡問題。

因爲SQL返回結果只有1條,且不存在大字段,很容易定位到是數據收集階段的問題,因而懷疑到了索引上。
再使用 explain或desc 看一下執行計劃:數據庫

type possible_key key extra
index PRIMARY idx_uid Using where; Using index

發現並無使用主鍵也就是id索引。因而問題已經很明顯了。最後給出優化方案。性能優化

在Mysql中id字段爲int型,where條件中使用 in(1, 2, 3) 是能夠命中索引的,使用 in("1","2","3") 經過mysql優化器的優化爲int型後也能夠命中索引,但當二者混用時,mysql不會對它進行優化,致使索引失敗。後面就是業務層的事情了。服務器

友鏈:https://www.yuque.com/threads...網絡

相關文章
相關標籤/搜索