mysql
案例一:粉絲查詢優化git
粉絲查詢有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
優化思路數據庫
簡化sql,自帶的userid的邏輯放到代碼層去處理緩存
優化後tomcat
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性能優化先後,有多大的差距,今天測試給你們看
以上不正之處請指出。
對於我說的要多多使用的索引優化,相關的內容我經過一張思惟導圖進行了整理和總結,其中包括如何操做,來看一下這張思惟導圖
須要這份學習文檔的,關注+轉發後,私信「資料」便可查看獲取方式
而除了索引優化以外,對於數據庫的優化還有一些其餘的方面,就像汽車維修同樣,你只有瞭解它的內部構造,才能更好的對他進行維護,因此除了性能調優以外,你還須要瞭解數據庫的相關構造,才能更好的進行性能優化,爲你們推薦一本書,內容從架構到優化全涵蓋,相信會對你的學習產生幫助
須要這份優化思惟導圖以及上面的知識圖的老鐵,添加小助手:msbxq2020免費獲取,同步的還有相關的視頻講解以及學習文檔,還不快點行動
關注公衆號:Java架構師聯盟,每日更新技術好文
部分資料已經上傳到個人git倉庫中:有須要的能夠下載