在優化有問題的查詢時,目標應該是找到一個更優的方法獲得實際需要的結果,而不是一定總是要求從MySQL獲取一模一樣的結果集 ...
在優化有問題的查詢時,目標應該是找到一個更優的方法獲得實際需要的結果,而不是一定總是要求從MySQL獲取一模一樣的結果集
一個複雜查詢還是多個簡單查詢
設計查詢的時候一定需要考慮的問題就是,是否需要將一個複雜的查詢分成多個簡單的查詢。
雖然在傳統實現中,總是強調需要在資料庫層完成儘可能多的工作,這是因為在過去總是認為網路通信、查詢解析和優化是一件代價很高的事情。
但是這樣的想法對於MySQL並不合適,因為MySQL從設計上就讓連接和斷開都很輕量,在返回一個小查詢結果方面十分高效。
MySQL內部每秒能夠掃描記憶體中上百萬行的數據,相比之下,MySQL響應數據給客戶端的速度就慢得多。在其他條件都相同的時候,使用儘可能少的查詢當然是更好的。但是有時候,將一個大的查詢分解為多個小查詢是很有必要的。
切分查詢
有時候需要對一個大查詢分而治之,將大查詢分為數個小查詢,每個查詢功能完全相同,只完成一小部分,每次只返回一小部分查詢結果。
刪除舊的數據就是一個很好的例子。定期清理大量數據時,如果使用一個大的語句一次性完成的話,可能需要鎖住很多數據,占用很多數據並且會阻塞很多小的但是很重要的查詢。
將一個大的DELETE語句切分成為多個較小的查詢可以儘可能小的影響MySQL性能。
分解關聯查詢
很多高性能的應用都會第關聯查詢進行分解。簡單地說,就是對每一個表進行一次單表查詢,然後將結果在應用程式中進行關聯。比如下麵這個查詢:
SELECT * FROM tag
JOIN tag_post ON tag_post.tag_id = tag.id
JOIN post ON tag_post.post_id = post.id
這個查詢可以分解成下麵這些查詢來代替:
SELECT * FROM tag WHERE tag = 'mysql';
SELECT * FROM tag_post WHERE tag_id = 1234;
SELECT * FROM post WHERE post.id in (123,456,789);
這樣拆分的好處是:
- 讓緩存的效率更加高效。 許多應用程式可以方便地緩存單表查詢對應的結果對象
- 減少查詢時可能遇到的鎖競爭
- 在應用層做關聯,可以更容易對資料庫進行拆分,做到高性能和可拓展
- 查詢本身效率也可能隨之提升。在這個例子中使用IN()代替關聯查詢,可以讓MySQL按照ID順序進行查詢,這可能會比隨機的關聯更加高效
- 可以減少冗餘記錄的查詢。在應用層進行關聯查詢,意味著對於某條記錄應用只需要查詢一次,而在資料庫中進行關聯查詢,則可能需要重覆的訪問一部分數據。這樣的重構有助於減少網路和記憶體的消耗。
- 在應用中實現了哈希關聯,而不是使用MySQL的嵌套迴圈關聯