MySQL慢查詢以及重構查詢的方式記錄
前言
什麼是慢查詢,如何優化慢查詢,下面介紹這兩個知識點的相關知識。
慢查詢基礎:優化數據訪問
是否向數據庫請求瞭不需要的數據
查詢不需要的記錄:解決方案:查詢後面加上Limit
多表關聯時返回全部列:解決方案:隻取需要的列
總是取出全部列:select * 解決方案:最好還是獲取部分列,除非應用程序處緩存列的數據瞭
重復查詢相同的數據:解決方案:需要時從緩存中取出
MySQL是否在掃描額外的記錄
可以從響應時間,掃描的行數,返回的行數來進行查詢開銷的衡量。
要想減少掃描行數可以使用索引對需要的記錄進行覆蓋,但是增加索引不意味著就能讓掃描的行數等於返回的行數,比如sum,count之類的聚合函數
重構查詢的方法
一個復雜查詢還是多個簡單查詢
在過去,總是強調需要數據庫層完成盡可能多的工作,因為過去網絡通信查詢解析和優化是一件代價很高的事情。
但是這樣的想法對於MySQL並不適用,MySQL從設計上讓連接和斷開連接都很輕量級,在返回一個小的查詢結果方面很高效。現代的網絡速度比以前要快很多,無論是帶寬還是延遲。在某些版本的MySQL上,即使在一個通用服務器上,也能夠運行每秒超過10萬的查詢,即使是一個千兆網卡也能輕松滿足每秒超過2000次的查詢。所以運行多個小查詢現在已經不是大問題瞭。
當然,相比較於內部掃描,響應數據給客戶端更加耗時,所以在同條件下,使用盡可能少的查詢更好。
切分查詢
當使用sql進行查詢時,需要註意將大查詢切分成小查詢,可以減少對數據庫的影響,因為一個大語句一次性完成的話,則可能一次鎖住很多數據,占滿整個事務日志,耗盡系統資源,阻塞其他查詢。
比如我們做數據統計時要對大量訂單號的信息進行查詢,那麼是一次性用in查詢,還是切割參數list多次查詢呢,答案是切割參數list多次查詢,因為當in裡面的參數過多時,MySQL就會認為再走索引已經不行瞭,可能就會進行全表查詢,如果這個時候數據表數據量過大,那可能就會造成查詢超時。
// chops a list into non-view sublists of length L static <T> List<List<T>> chopped(List<T> list, final int L) { List<List<T>> parts = new ArrayList<List<T>>(); final int N = list.size(); for (int i = 0; i < N; i += L) { parts.add(new ArrayList<T>( list.subList(i, Math.min(N, i + L))) ); } return parts; } List<Integer> numbers = Collections.unmodifiableList( Arrays.asList(5,3,1,2,9,5,0,7) ); List<List<Integer>> parts = chopped(numbers, 3); System.out.println(parts); // prints "[[5, 3, 1], [2, 9, 5], [0, 7]]" parts.get(0).add(-1); System.out.println(parts); // prints "[[5, 3, 1, -1], [2, 9, 5], [0, 7]]" System.out.println(numbers); // prints "[5, 3, 1, 2, 9, 5, 0, 7]" (unmodified!)
在程序中將list截斷,從而使查詢能使用索引而不是進行全表掃描。
阿裡開發手冊中就推薦仔細評估in後面的集合元素數量,控制在1000個之內。
分解關聯查詢
將多表inner join 進行分解,分解成小查詢,超過三個表的join,就需要禁止瞭。
優點有:
- 緩存的效率會更高,
- 分解後的查詢可以減少鎖的競爭
- 應用層可以緩存查詢數據,減小數據庫的壓力。
- 可以提升查詢效率,因為用主鍵之類進行in查詢,比按照條件范圍查詢可能會更高效,尤其是大表的時候。
- 可以減少冗餘記錄的查詢
- 更進一步,這樣做相當於在應用中實現瞭哈希關聯,而不是使用MySQL的嵌套循環關聯。某些場景哈希關聯的效率要高很多。
總結
到此這篇關於MySQL慢查詢以及重構查詢的文章就介紹到這瞭,更多相關MySQL慢查詢重構查詢內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!