16 「order by」是怎麼工作的?

2021-09-24 01:12:25 字數 2233 閱讀 4158

示例語句:select city,name,age from t where city='杭州' order by name limit 1000;

mysql會給每個執行緒分配一塊記憶體用於排序,稱為sort_buffer。

city索引示意圖:

通常情況這個語句的執行流程如下所示:

初始化sort_buffer,確定放入name,city,age這三個字段;

從索引city找到第乙個滿足city='杭州'條件的主鍵id,也就是上圖中id_x;

到主鍵id索引取出整行,取name,city,age三個欄位的值,存入sort_buffer中;

從索引city取下乙個記錄的主鍵id;

重複步驟3、4直到city的值不滿足查詢條件為止,對應的主鍵id也就是圖中的id_y;

對sort_buffer中的資料按照欄位name做快速排序;

按照排序結果取前1000行返回給客戶端。

流程圖如下:

全欄位排序的排序過程可能在記憶體中完成,也可能使用外部排序,取決於排序所需的記憶體和引數sort_buffer_size。

sort_buffer_size,就是mysql為排序開闢的記憶體(sort_buffer)的大小。如果要排序的資料量小於sort_buffer_size,排序就在記憶體中完成,否則就要利用磁碟臨時檔案輔助排序。

外部排序可能會使用到多個臨時檔案,因為外部排序一般使用歸併排序演算法,每個檔案單獨排序,然後將這些排序後的臨時檔案合併成乙個有序的大檔案。

sort_buffer_size越小,需要分成的份數就越多。

全欄位培訓只對原表資料讀了一遍,剩下的都是在sort_buffer和臨時檔案中執行的。但是有個問題,如果查詢要返回的字很多,那麼sort_buffer裡面要放的字段數太多,這樣記憶體裡能夠同時放下的行數很少,要分成很多個臨時檔案,排序效能會很差。

如果mysql認為排序的單行長度太大會怎麼做呢?

引數max_length_for_sort_data,是mysql中專門控制用於排序的行資料長度的乙個引數。意思是,如果當行的長度(用於排序的所有字段定義長度的總和)超過這個值,mysql就認為單行太大,要還乙個演算法。

新的演算法放入sort_buffer的字段,只有要排序的列(即name)和主鍵id。

但這時因為排序結果少了字段,不能直接返回,整個執行流程如下:

初始化sort_buffer,確定放入兩個字段,即name和id;

從索引city找到第乙個滿足條件city='杭州'的主鍵id;

到主鍵id索引取出整行,取name,id這兩個字段放入sort_buffer中;

從索引city取下乙個記錄的主鍵id;

重複步驟3、4直到不滿足city='杭州'條件為止;

對sort_buffer中的資料按照欄位name進行排序;

遍歷排序結果,取前1000行,並按照id的值回到原表中取出city、name和age三個字段返回給客戶端。

執行流程如下圖:

說明:最後的「結果集」是乙個邏輯概念,根據主鍵id查到所需要的字段後直接就返回給客戶端了,不會再占用記憶體儲存結果。

如果mysql實在是擔心排序記憶體太小,會影響排序效率,才會採用rowid排序演算法,這樣排序過程中一次可以排序更多行,但是需要再回表去取資料。

如果mysql認為記憶體足夠大,會優先選擇全欄位排序,把所有欄位都放在sort_buffer中完成排序。

這也就提現了mysql的乙個設計思想:如果記憶體夠,就要多利用記憶體,儘量減少磁碟訪問。

對於innodb來說,rowid排序會要求回表多造成磁碟讀,因此不會被優先選擇。

並不是所有的order by語句都需要排序,如果字段天然就是有序的,就不需要排序了。

比如可以給city和name建立聯合索引,這樣name本來就是有序的了。

還有索引覆蓋索引上的資訊足夠滿足資訊查詢,不需要再回表。可以建立city,name,age的聯合索引。

當然並不是為每個查詢都用上覆蓋索引,畢竟索引也是又維護代價的,需要權衡決定。

「orderby」是怎麼工作的

假設你要查詢城市是 杭州 的所有人名字,並且按照姓名排序返回前1000個人的姓名 年齡。假設這個表的部分定義是這樣的 create table t id int 11 notnull city varchar 16 not null name varchar 16 not null age int ...

mysql的orderby是如何工作的

1.建表語句 create table t id int 11 not null,city varchar 16 not null,name varchar 16 not null,age int 11 not null,addr varchar 128 default null,primary k...

heartbeat是怎麼工作的

因為我們要提供 高可用性 所以要考慮到 導演 突然罷工的情形 因此我們要安排兩個導演,也 就是要有兩個排程伺服器節點。這兩個節點的地位不同,其中乙個是主節點,另外乙個是輔節點 可以看成是乙個 主導演 和乙個 副導演 這兩個節點正是 用heartbeat來互相監測對方的。heartbeat可以通過乙太...