一次資料庫效能優化測試,整理最全資料庫優化方案,還不快收藏
案例一:粉絲查詢優化
粉絲查詢有2條sql
--查詢所有粉絲
SELECT user FROM osc_friends f INNER JOIN osc_users u
ON u.id=f.user AND f.friend=? AND f.user<>? ORDER BY create_time DESC
--查詢粉絲數量
SELECT COUNT(friend) FROM osc_friends f INNER JOIN osc_users u
ON u.id=f.user AND f.friend = ? AND f.user <> ?
這兩個查詢在業務可以優化,inner join一個osc_users表目的是去掉osc_friends裡面自帶了自己的userid,偏偏osc_users表是比較大的表,為啥這樣設計,可以看看早年紅薯分享的OSChina 使用者動態設計說明
優化思路
簡化sql,自帶的userid的邏輯放到程式碼層去處理
優化後
SELECT user FROM osc_friends f WHERE f.friend=? ORDER BY create_time DESC
SELECT COUNT(*) FROM osc_friends f WHERE f.friend = ?
sql簡化了很多,大大提升了查詢速度
小結
有時候業務處理放到程式碼層,能達到意想不到的效果
案例二:私信優化
SELECT MAX(id) AS id, COUNT(id) AS msgCount
FROM osc_msgs WHERE user = 12 GROUP BY friend ORDER BY id DESC
osc_msgs表儲存著所有的私信紀錄,隨著時間推移,該錶慢慢變大,一次查詢成本變高,基本都要1秒多
優化思路
取私信表的最新的兩個人的對話放入一個新建的osc_last_msgs表,每次發私信更新osc_last_msgs表,這個表只記錄最新的私信,這樣優化後的私信列表sql就不需要在msg表裡面找資料,只需要去osc_last_msgs表尋找.
優化後
SELECT * FROM osc_last_msgs WHERE user=? ORDER BY msg_id DESC
小結
把資料量從大化小的典型案例
案例三 評論優化
SELECT
l1.id
FROM
osc_opt_logs l1,
osc_opt_logs l2
WHERE
l1.obj_type IN (101, 111, 113, 116, 119, 121)
AND l2.obj_type IN (
100,
110,
112,
114,
118,
120,
123,
124,
122,
125,
126,
127,
99
)
AND l1.parent_id = l2.id
AND l2. USER = 12
ORDER BY
l1.id DESC
LIMIT 20;
嘗試建立聯合索引進行優化,不過效果不佳,因為optlog表特別的大,因此聯表查詢效率極低,佔用查詢快取空間極大。
優化思路
新增一個reply_user欄位,將回復的動彈進行標記,這樣子就可以簡化整個聯表查詢操作
優化後
SELECT id FROM osc_opt_logs where reply_user = 12 ORDER BY id DESC limit 20;
小結
適當的冗餘欄位可以降低sql的複雜度
案例四 索引優化
索引優化主要還是依賴explain命令,關於explain命令相信大家並不陌生,具體用法和欄位含義可以參考官網explain-output,這裡需要強調rows是核心指標,絕大部分rows小的語句執行一般很快。所以優化語句基本上都是在優化rows。
一般來說.
-
rows<1000,是在可接受的範圍內的。
-
rows在1000~1w之間,在密集訪問時可能導致效能問題,但如果不是太頻繁的訪問(頻率低於1分鐘一次),又難再優化的話,可以接受,但需要注意觀察
-
rows大於1萬時,應慎重考慮SQL的設計,優化SQL
這個沒有絕對值可參考,一般來說越小越好,,如果100萬資料量的資料庫,rows是70萬,通過這個可以判斷sql的查詢效能很差,如果100萬條資料量的資料庫,rows是1萬,從我個人的角度,還是能接受的。
另外就是extra的資訊,該列包含MySQL解決查詢的詳細資訊 ,重點關注出現關鍵字:
Using filesort:當Query 中包含order by 操作,而且無法利用索引完成排序操作的時候,MySQL Query Optimizer 不得不選擇相應的排序演算法來實現。
Using temporary:在某些操作中必須使用臨時表時,在 Extra 資訊中就會出現Using temporary ,主要常見於 GROUP BY 和 ORDER BY 等操作中
當執行計劃Extra 出現Using filesort 、Using temporary 時,可以考慮是否需要進行sql優化和調整索引,最後再調整my.cnf 中與排序或者臨時表相關的引數,如sort_buffer_size或者tmp_table_size.
比如下面這個:
原因是mysql查詢只使用一個索引,如果where字句用了索引的話,那麼order by 中的列是不會使用索引的。所以order by的條件也需要新增到索引裡面組成聯合索引,優化後
還有一個需要注意的點是,索引有個最左字首的原則:聯合索引(a,b,c)可以匹配(a)、(a,b)、(a,b,c)但不可以匹配(b,c)
小結
explain SQL語句應該是日常開發中的習慣動作,有時explain出來的結果,可能會出於偏離設計的意料之外
案例五 關注資料庫狀態
當滿滿期待優化後有大幅度效能提升的時候,現實總是跟你開玩笑,經過測試檢查,發現不是sql的問題,有可能是跟伺服器有關,用top命令看了發現mysql程序的cpu佔用率一直在100%左右,這就奇怪了,用show processlist看了一下mysql的程序,發現一個可疑的sql一直在執行,kill 掉後cpu佔用率馬上下來了
小結
當你發現數據庫cpu或者io有異常現象時候,用show processlist看看資料庫在忙什麼
寫在最後
經過這次優化,個人空間開啟速度提升了,總結幾條心得:
1.不要指望所有SQL語句都能通過SQL優化,業務上的調整帶來意想不到的效果;
2.所有的效能優化都是空間換時間,通過冗餘來提高效能,大體思路都是大化小,分而治之
3.explain是sql優化的入門
4.索引利大於弊,多用,善用之
如果再卡,可能會從分庫分表,讀寫分離這方面入手了。
優化前跟優化後的mysql是大大的不同,同樣用mysql,支撐起了淘寶,騰訊,facebook,但卻對你的業務系統支撐起來很吃力?
就像之前寫過的tomcat的相關內容:Tomcat效能優化前後,有多大的差距,今天測試給大家看
以上不正之處請指出。
對於我說的要多多使用的索引優化,相關的內容我通過一張思維導圖進行了整理和總結,其中包括如何操作,來看一下這張思維導圖
需要這份學習文件的,關注+轉發後,私信“資料”即可檢視獲取方式
而除了索引優化之外,對於資料庫的優化還有一些其他的方面,就像汽車維修一樣,你只有瞭解它的內部構造,才能更好的對他進行維護,所以除了效能調優之外,你還需要了解資料庫的相關構造,才能更好的進行效能優化,為大家推薦一本書,內容從架構到優化全涵蓋,相信會對你的學習產生幫助
目錄
架構
建立高效能索引
查詢效能優化
可擴充套件的mysql
應用層調優
應用工具
附錄
需要這份優化思維導圖以及上面的知識圖的老鐵,新增小助手:msbxq2020免費獲取,同步的還有相關的視訊講解以及學習文件,還不快點行動
關注公眾號:Java架構師聯盟,每日更新技術好文
部分資料已經上傳到我的git倉庫中:有需要的可以下載
https://gitee.com/biwangsheng/mxq