MySQL中Order By實現原理分析

2021-09-08 03:20:34 字數 1774 閱讀 3278

下面將通過例項分析兩種排序實現方式及實現**:

假設有 table a 和 b 兩個表結構分別如下:

1、利用有序索引進行排序,實際上就是當我們query 的order by 條件和query 的執行計畫中所利用的index的索引鍵(或前面幾個索引鍵)完全一致,且索引訪問方式為rang、ref 或者index的時候,mysql可以利用索引順序而直接取得已經排好序的資料。這種方式的order by 基本上可以說是最優的排序方式了,因為mysql不需要進行實際的排序操作。

假設我們在table a和b上執行如下sql:

我們通過執行計畫可以看出,mysql實際上並沒有進行實際的排序操作,實際上其整個執行過程如下圖所示:

2、通過相應的排序演算法,將取得的資料在記憶體中進行排序方式,mysql 比需要將資料在記憶體中進行排序,所使用的記憶體區域也就是我們通過sort_buffer_size 系統變數所設定的排序區。這個排序區是每個thread 獨享的,所以說可能在同一時刻在mysql 中可能存在多個 sort buffer 記憶體區域。

第二種方式在mysql query optimizer 所給出的執行計畫(通過 explain 命令檢視)中被稱為filesort。在這種方式中,主要是由於沒有可以利用的有序索引取得有序的資料,mysql只能通過將取得的資料在記憶體中進行排序然後再將資料返回給客戶端。在mysql中filesort 的實現演算法實際上是有兩種的,一種是首先根據相應的條件取出相應的排序欄位和可以直接定位行資料的行指標資訊,然後在sort buffer 中進行排序。另外一種是一次性取出滿足條件行的所有字段,然後在sort buffer中進行排序。

在mysql4.1版本之前只有第一種排序演算法,第二種演算法是從mysql4.1開始的改進演算法,主要目的是為了減少第一次演算法中需要兩次訪問表資料的 io 操作,將兩次變成了一次,但相應也會耗用更多的sort buffer 空間。當然,mysql4.1開始的以後所有版本同時也支援第一種演算法,mysql主要通過比較我們所設定的系統引數 max_length_for_sort_data的大小和query 語句所取出的字段型別大小總和來判定需要使用哪一種排序演算法。如果 max_length_for_sort_data更大,則使用第二種優化後的演算法,反之使用第一種演算法。所以如果希望 order by 操作的效率盡可能的高,一定要主義 max_length_for_sort_data 引數的設定。曾經就有同事的資料庫出現大量的排序等待,造成系統負載很高,而且響應時間變得很長,最後查出正是因為mysql 使用了傳統的第一種排序演算法而導致,在加大了max_length_for_sort_data 引數值之後,系統負載馬上得到了大的緩解,響應也快了很多。

我們再看看 mysql 需要使用filesort 實現排序的例項。

假設我們改變一下我們的query,換成通過a.c2來排序,再看看情況:

mysql 從 table a 中取出了符合條件的資料,由於取得的資料並不滿足order by 條件,所以mysql進行了 filesort 操作,其整個執行過程如下圖所示:

在mysql 中,filesort 操作還有乙個比較奇怪的限制,那就是其資料來源必須是**於乙個table,所以,如果我們的排序資料如果是兩個(或者更多個) table 通過join所得出的,那麼 mysql 必須通過先建立乙個臨時表(temporary table),然後再將此臨時表的資料進行排序,如下例所示:

這個執行計畫的輸出還是有點奇怪的,不知道為什麼,mysql query optimizer 將 「using temporary」 過程顯示在第一行對table a 的操作中,難道只是為讓執行計畫的輸出少一行?

實際執行過程應該是如下圖所示:

MySQL中order by的工作原理

假設有查詢語句 select city,name,age from t where city 杭州 order by name limit 1000,且city上建立索引。mysql為order by排序開闢的記憶體稱為sort buffer,如果要排序的資料量小於這塊記憶體,則在記憶體中進行排序。...

關於mysql中orderby的幾個注意事項

在mysql php查詢中 對字段的型別要求比較高 例如varchar 11 和int 這兩種型別 在許多時候可以通用但是在下面這種情況時候最好還是選擇int而不要選擇varchar 11 table list 欄位名 型別 id int auto increment list id varchar...

MySQL如何優化ORDER BY

某些情況中,mysql可以使用乙個索引來滿足order by子句,而不需要額外的排序。即使order by不確切匹配索引,只要where子句中的所有未使用的索引部分和所有額外的order by 列為常數,就可以使用索引。下面的查詢使用索引來解決order by部分 某些情況中,mysql可以使用乙個...