天天看點

MySQL--- order by 是怎麼工作的?

 “order by”是怎麼工作的?

explain指令看語句的執行情況:

Extra 這個字段中的“Using filesort”表示的就是需要排序,MySQL 會給每個線程配置設定一塊記憶體用于排序,稱為 sort_buffer。

select city,name,age from t where city='杭州' order by name limit 1000  ;

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

1.初始化 sort_buffer,确定放入 name、city、age 這三個字段;

2.從索引 city 找到第一個滿足 city='杭州’條件的主鍵 id,也就是圖中的 ID_X;

3.到主鍵 id 索引取出整行,取 name、city、age 三個字段的值,存入 sort_buffer 中;

4.從索引 city 取下一個記錄的主鍵 id;

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

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

7.按照排序結果取前 1000 行傳回給用戶端。

“按name排序”這個動作,可能在記憶體中完成,也可能需要使用外部排序,這取決于排序所需的記憶體和參數 sort_buffer_size。

sort_buffer_size,就是 MySQL 為排序開辟的記憶體(sort_buffer)的大小。如果要排序的資料量小于 sort_buffer_size,排序就在記憶體中完成。但如果排序資料量太大,記憶體放不下,則不得不利用磁盤臨時檔案輔助排序。

你可以用下面介紹的方法,來确定一個排序語句是否使用了臨時檔案。

SET optimizer_trace='enabled=on'; 

select VARIABLE_VALUE into @a from  performance_schema.session_status where variable_name = 'Innodb_rows_read';

select city, name,age from t where city='杭州' order by name limit 1000; 

SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G

select VARIABLE_VALUE into @b from performance_schema.session_status where variable_name = 'Innodb_rows_read';

select @[email protected];

建立一個 city 和 name 的聯合索引:

整個查詢過程的流程就變成了:

1.從索引 (city,name) 找到第一個滿足 city='杭州’條件的主鍵 id;

2.到主鍵 id 索引取出整行,取 name、city、age 三個字段的值,作為結果集的一部分直接傳回;

3.從索引 city 取下一個記錄主鍵 id;

4.重複步驟 2、3,直到查到第 1000 條記錄,或者是不滿足 city='杭州’條件時循環結束。

這個語句的執行流程有沒有可能進一步簡化呢?

建立一個 city、name 和 age 的聯合索引:

1.從索引 (city,name,age) 找到第一個滿足 city='杭州’條件的記錄,取出其中的 city、name 和 age 這三個字段的值,作為結果集的一部分直接傳回;

2.從索引(city,name,age)取下一個記錄,同樣取出這三個字段的值,作為結果集的一部分直接傳回;

3.重複執行步驟 2,直到查到第 1000 條記錄,或者是不滿足 city='杭州’條件時循環結束。    

Extra 字段裡面多了“Using index”,表示的就是使用了覆寫索引,性能上會快很多。

繼續閱讀