MYSQL 排序和分組


一.MYSQL 中有兩種排序方式:
1:通過有序索引順序掃描直接返回有序數據,這種方式在使用explain 分析查詢的時候顯示為Using Index ,不需要額外的排序,操作效率較高。
2: 是通過對返回數據進行排序,也就是通常說的filesort 排序,所有不是通過索引直接返回排序結果都叫filesort排序。filesort 並不代表磁盤文件進行排序,而只是說明了進行一個排序操作,至於排序操作是否使用了磁盤文件或臨時表等,則取決於mysql 服務器對排序參數的設置和需要排序數據的大小。例如,按照商店store_id 排序返回所有客戶記錄時,出現了對全表掃描的結果排序:
explain select * from customer order by store_id
Extra : Using filesort
 
又如,只需要獲取商店store_id 和顧客email 信息時,對表customer 的掃描就被覆蓋索引idx_storeid_email 掃描替代,此時雖然只訪問了索引就足夠,但是在索引idx_stored_email 上發生了一次排序操作,所以執行計划仍然有 using filesort.
alter table customer add index idx_storeid_email(store_id,email);
 
explain select store_id ,email ,customer_id from customer order by email
extra :Using Index ,Using filesort
 
 
Filesort 是通過相應的排序算法,將取得的數據在sort_buffer_size 系統變量設置的內存排序區中進行排序,如果內存裝載不下,它就會將磁盤上的數據進行分區,再對各個數據塊進行排序,然后將各個塊合並成有序的結果集。sort_buffer_size 設置的排序區是每個線程獨占的,所以同一個時刻,mysql 中存在多個sort buffer 排序區.
 
了解了mysql 排序的方式,優化目標就清晰了:盡量減少額外的排序,通過索引直接返回有序數據。where 條件和order by 使用相同的索引,並且order by 的順序和索引順序相同,並且order by 的字段都是生序或者都是降序,否則肯定需要額外的排序操作,這樣就會出現filesort.
總結,下列SQL 可以使用索引:
select * from tabname order by key_part1,key_part2,......;
select * from tabname where key_part1 order by key_part1 desc ,key_part2 desc;
select * from tabname order by key_part1,key_part2 desc;
 
但是在以下幾種情況下則不使用 索引:
 
select * from tabname order by key_part1 desc ,key_part2 asc;
-- order by 的字段混合ASC 和 DESC
select * from tabname where key2=constant order by key1;
-- 用於查詢行的關鍵字與order by 中所使用的不相同
select * from tabname order by key1,key2;
-- 對不同的關鍵字使用order by :
 
 
二.Filesort 的優化
通過創建合適的索引能夠減少filesort 出現,但是在某些情況下,條件限制不能讓filesort 消失,那就需要想辦法加快 filesort 的操作。對於filesort ,MYSQL 有兩種排序算法。
1.兩次掃描算法(Two passes):首先根據條件取出排序字段和行指針信息,之后在排序區sort buffert 中排序。如果排序區sort buffer 不夠,則在臨時表temporary table 中存儲排序結果。完成排序后根據行指針回表讀取記錄。該算法是mysql 4.1 之前采用的算法,需要兩次訪問數據,第一次獲取排序字段和行指針信息,第二次根據行指針獲取記錄,尤其是第二次讀取操作可能導致大量隨機 I/O 操作;優點是排序的時候內存呢開銷哦較少。
 
2. 一次掃描算法(Single pass):一次行取出滿足條件的行的所有字段,然后在排序區sort buffer 中排序后直接輸出結果集。排序的時候內存開銷比較大,但是排序效率比兩次掃描算法要高。
 
MySQL 通過比較系統變量 max_length_for_sort_data 的大小和Query 語句取出的字段總大小來判斷使用哪種 排序算法。如果 max_length_for_sort_data更大,那么使用第二種優化之后的算法;否則使用第一種算法。
適當加大系統變量max_length_for_sort_data 的值,能夠讓 mysql 選擇更優化的filesort 排序算法。當然,假如 max_length_for_sort_data 設置過大,會造成cpu 利用率過低和磁盤I/ O過高,cpu 和I/O利用平衡就足夠了。
 
 
適當加大sort_buffer_size 排序區,盡量讓排序在內存中完成,而不是通過創建臨時表放在文件中進行;當然也不能無限制加大 sort_buffer_size 排序區,因為sort_buffer_size 參數是每個線程獨占的,設置過大,會導致服務器SWAP 嚴重,要考慮數據庫活動連接數和服務器內存的大小來適當設置排序區。
盡量使使用必要的字段,select 具體的字段名稱,而不是 select * 選擇 所有字段,這樣可以減少排序區的使用,提高SQL 性能。
 
三. 優化 Group BY 語句
如果查詢包含Group by 但用戶想要 避免排序結果的消耗,則可以指定order by null 禁止排序。
explain select payment_date,sum(amount) from payment group by payment_fate
extra : Using temporary;Using filesort
 
explain select payment_date,sum(amount) from payment_date order by null
extra : Using temporary
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM