前言:之前實習時候做過一陣子的查詢優化,那段時間結合閱讀《高性能MySQL》,有些心得體會,現在重新總結。圍繞著《高性能mysql》,同時加入自己的心得體會。
(一)慢查詢的原因
1,是否向數據庫請求不必要的數據
(1)查詢不需要的數據
簡單來說,就是獲取全部全部的結果再進行篩選,然後拋棄大部分的數據,其實這些數據可以不用篩選出來的,我們可以通過加limit等方式解決
(2)多表關聯返回全部列
這種情況之前在優化時候很常見,很多人都會寫出類似下面這樣的語句:
SELECT * FROM tab1
這樣寫將會返回三個表的全部數據列,正確的方式應該是隻取需要的。我們每次在看到SELECT * 的時候,都要問問這樣是否必要, 有時候是為了擴展性,如果在自己明白代價的情況下,也是可以接受的。
(二)是否掃描額外的記錄
我們看到返回的數據是我們需要的,但是應該繼續看看返回結果是否掃描了過多的數據,這裡有三個指標:響應時間,掃描的行數,返回的行數。我們可以使用explain來查看。這裡就不展開了。
(三)重構查詢的方式
1,是否可以將一個複雜查詢分成多個簡單查詢
我們寫複雜查詢的原因是想讓數據庫儘量一次性完成儘可能多的任務,認為網絡通信,查詢解析和優化是代價很高的事情。但是現在已經不是這樣了。但是這樣切分是要合理的,不能把原來的好的查詢硬要拆開。接下來將說說拆分的技巧
2,切分查詢
接下來舉個例子來說明應用場景。我們如果需要每個月定期刪除大量的舊數據,如果用一個語句來完成,那麼將會鎖住大量的數據,系統資源會被耗盡,同時還可能阻塞其他事務,甚至發生死鎖。那麼,我們就可以進行拆分。
原語句:
DELETE FROM tab WHERE create_time < DATE_SUB(NOW(),INTERVAL 3 MONTH);11
拆分為:
row = 0;do { row = do_query("DELETE FROM tab WHERE create_time < DATE_SUB(NOW(),INTERVAL 3 MONTH) LIMIT 10000")
一次性刪除一萬條,我覺得對於服務器來說很OK,而且每次刪除完我們還可以暫停一會。
3,分解關聯查詢
(這裡就全部借鑑這本書了,之前要拆分,但是老大不讓,所以沒什麼實際體會)
首先來看一個例子
SELECT * FROM tag
可以拆分為
SELECT * FROM tag WHERE tag='mysql';SELECT * FROM tag_post WHERE tag_id=1234;SELECT * from post WHERE post.id in (124,456,567,9098,8904);123123
那麼來看看這樣的好處
(1)緩存的效率更高。我們很多應用程序可以很方便緩存單筆查詢對應的結果對象,例如如果tag被緩存了,那麼第一條查詢就可以跳過了。對於mysql的查詢緩存來說,如果關聯中的某個表發生變化,那麼就無法使用緩存,而拆分後,如果有某個表很少該表,那麼基於該表的查詢就可以重複利用查詢緩存結果了
(2)執行單個查詢可以減少鎖的競爭
(3)應用層做關聯,可以更容易對數據庫進行拆分,更容易做到高性能和擴展性
1、具有1-5工作經驗的,面對目前流行的技術不知從何下手,
需要突破技術瓶頸的可以加。2、在公司待久了,過得很安逸,
但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。
3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,
常用設計思想,常用java開發框架掌握熟練的,可以加。
4、覺得自己很牛B,一般需求都能搞定。
但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。
5. 群號:高級架構群 478052716備註好信息!
6.阿里Java高級大牛直播講解知識點,分享知識,
多年工作經驗的梳理和總結,帶著大家全面、
科學地建立自己的技術體系和技術認知!