mysql排序與分類彙總 MYSQL 排序和分組

2021-10-17 16:38:12 字數 2984 閱讀 8173

一.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

MySQL彙總排序查詢

兩個要求 計算出來的字段銷售總額保留兩位小數 排序時,彙總不參與排序,放在最下面。case when 加彙總,但是orderby排序對所有行排序,彙總的銷售金額最大一直在最上面 select case when grouping 店鋪名稱 1 then 彙總 else 店鋪名稱 end 店鋪名稱,r...

mysql與php的連線 PHP 連線mysql

php 連線mysql mysqlhost localhost mysqluser root mysqlpass mysqldata mydata connect mysql connect mysqlhost,mysqluser,mysqlpass or die 錯誤 mysql error my...

常見排序演算法彙總與分析(下)(基數排序與計數排序)

本篇彙總的演算法將不再是基於比較的排序演算法,因此會突破這類演算法的時間複雜度下界o nlog2n 如果有朋友對前面的內容感興趣,可以先去看看常見排序演算法彙總與分析 中 選擇排序與歸併排序 我們先來總結基數排序演算法,該演算法在排序過程中不進行比較,而是通過 分配 和 收集 兩個過程來實現的。基本...