《Mysql Order By 的工作原理?》

2022-05-02 08:48:13 字數 3117 閱讀 9012

一:概述

- order by 用於 sql 語句中的排序。

- 以  select city,name,age from t where city='杭州' order by name limit 1000 ; 舉例,來了解下排序的工作原理。

- 為了避免其他因素的影響,我們為 city 字段加上索引。

二:分析排序

- 分析

-  使用 explain 命令來看看這個語句的執**況。

- 可以看到,在 extra 這個欄位中的「using filesort」表示的就是需要排序。

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

二:全欄位排序(排序欄位未使用索引)

- 什麼時候使用全欄位排序?

- 欄位較少,資料量較小,排序可在記憶體中完成,mysql 的大部分不走索引的排序都是使用 全欄位排序完成的。

- 全欄位索引排序流程

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

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

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

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

- 重複步驟 3、4 直到 city 的值不滿足查詢條件為止。

-對 sort_buffer 中的資料按照字段 name 做快速排序;

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

- 流程細節

- 整個的排序動作,可能在記憶體中完成,也可能需要使用外部排序,這取決於排序所需的記憶體和引數 sort_buffer_size。

- sort_buffer_size,就是 mysql 為排序開闢的記憶體(sort_buffer)的大小。

- 如果要排序的資料量小於 sort_buffer_size,排序就在記憶體中完成。

- 但如果排序資料量太大,記憶體放不下,則不得不利用磁碟臨時檔案輔助排序。外部排序一般使用歸併排序演算法。

三: rowid 排序(排序欄位未使用索引)

- 什麼時候使用 rowid 排序?

- 在 全欄位排序 中,只對原表的資料讀了一遍,剩下的操作都是在 sort_buffer 和臨時檔案中執行的。

- 但是存在乙個問題,如果查詢要返回的字段很多,sort_buffer 放的字段數太多,這樣記憶體裡能夠同時放下的行數很少,要分成很多個臨時檔案,排序的效能會很差。

- mysql 認為 全欄位排序代價太大,於是使用 rowid 演算法排序。

- rowid 排序流程

- 初始化 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 三個字段返回給客戶端。 

- 流程細節

-  對比 全欄位排序流程你會發現,rowid 排序多訪問了一次表 的主鍵索引

四: 全欄位排序 對比 rowid 排序?

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

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

五:索引排序(排序字段使用索引)

- 新建立排序字段索引

- 還是上面的 sql 查詢, 這裡建立 city,name 的聯合索引。

- 再看索引排序流程

- 從索引 (city,name) 找到第乙個滿足 city='杭州』條件的主鍵 id。

-到主鍵 id 索引取出整行,取 name、city、age 三個欄位的值,作為結果集的一部分直接返回;

- 從索引 (city,name) 取下乙個記錄主鍵 id;

- 重複步驟 2、3,直到查到第 1000 條記錄,或者是不滿足 city='杭州』條件時迴圈結束。

六:排序欄位加索引的優點

- 在排序欄位有索引的情況下,查詢過程不需要臨時表,也不需要排序。

- 同時,也不會掃瞄全部符合條件的行數,而是找到適合條件既會返回資料。

七:其他在排序中中需要注意的。

- 無條件查詢如果只有order by create_time,即便create_time上有索引,也不會使用到。

- 因為優化器認為走二級索引再去回表成本比全表掃瞄排序更高。所以選擇走全表掃瞄,然後根據老師講的兩種方式選擇一種來排序

- 無條件查詢但是是order by create_time limit m.如果m值較小,是可以走索引的.

- 因為優化器認為根據索引有序性去回表查資料,然後得到m條資料,就可以終止迴圈,那麼成本比全表掃瞄小,則選擇走二級索引。

- 即便沒有二級索引,mysql針對order by limit也做了優化,採用堆排序。

MySQL order by工作機制

當使用order by對查詢結果進行排序時,mysql會給每個執行緒分配一塊兒記憶體sort buffer用於排序,在使用索引的情況下,整個的排序過程如下所述 1.初始化sort buffer,確定放入結果中所需的字段 2.從索引中找到第乙個滿足條件主鍵id 3.到主鍵id索引取出整行,取所需字段的...

mysql order by是怎麼工作的?

假設我們要查詢乙個市民表中城市 杭州的所有人的名字,並且按照名字排序 create table t id int 11 not null city varchar 16 not null name varchar 16 not null age int 11 not null addr varcha...

Mysql order by語句的優化

在某些情況中,mysql可以使用乙個索引來滿足order by子句,而不需要額外的排序。where條件和order by使用相同的索引,並且order by的順序和索引順序相同,並且order by的字段都是公升序或者都是降序。例如 下列sql可以使用索引。select from t1 order ...