MySQL Order By索引優化

2021-12-30 07:50:55 字數 2915 閱讀 5533

在一些情況下,mysql可以直接使用索引來滿足乙個order by 或group by 子句而無需做額外的排序。儘管order by 不是和索引的順序準確匹配,索引還是可以被用到,只要不用的索引部分和所有的額外的order by 欄位在where 子句中都被包括了。

使用索引的mysql order by

下列的幾個查詢都會使用索引來解決order by 或group by 部分:

select * from t1 order by key_part1,key_part2,... ;

select * from t1 where key_part1=constant order by key_part2;

select * from t1 where key_part1=constant group by key_part2;

select * from t1 order by key_part1 desc, key_part2 desc;

select * from t1 where key_part1=1 order by key_part1 desc, key_part2 desc;

不使用索引的mysql order by

在另一些情況下,mysql無法使用索引來滿足order by,儘管它會使用索引來找到記錄來匹配where 子句。這些情況如下:

* 對不同的索引鍵做order by :

select * from t1 order by key1, key2;

* 在非連續的索引鍵部分上做order by:

select * from t1 where key2=constant order by key_part2;

* 同時使用了asc 和desc:

select * from t1 order by key_part1 desc, key_part2 asc;

* 用於搜尋記錄的索引鍵和做order by 的不是同乙個:

select * from t1 where key2=constant order by key1;

* 有很多表一起做連線,而且讀取的記錄中在order by 中的字段都不全是來自第乙個非常數的表中(也就是說,在explain 分析的結果中的第乙個表的連線型別不是const)。

* 使用了不同的order by 和group by 表示式。

* 表索引中的記錄不是按序儲存。例如,hash 和heap 表就是這樣。

通過執行explain select ... order by,就知道mysql是否在查詢中使用了索引。如果extra 欄位的值是using filesort,則說明mysql無法使用索引。詳情請看"7.2.1 explain syntax (get information about a select)"。當必須對結果進行排序時,mysql 4.1以前 它使用了以下filesort 演算法:

1. 根據索引鍵讀取記錄,或者掃瞄資料表。那些無法匹配where 分句的記錄都會被略過。

2. 在緩衝中每條記錄都用乙個『對』儲存了2個值(索引鍵及記錄指標)。緩衝的大小依據系統變數sort_buffer_size 的值而定。

3. 當緩衝慢了時,就執行qsort(快速排序)並將結果儲存在臨時檔案中。將儲存的塊指標儲存起來(如果所有的『對』值都能儲存在緩衝中,就無需建立臨時檔案了)。

4. 執行上面的操作,直到所有的記錄都讀取出來了。

5. 做一次多重合併,將多達mergebuff(7)個區域的塊儲存在另乙個臨時檔案中。重複這個操作,直到所有在第乙個檔案的塊都放到第二個檔案了。

6. 重複以上操作,直到剩餘的塊數量小於mergebuff2 (15)。

7. 在最後一次多重合併時,只有記錄的指標(排序索引鍵的最後部分)寫到結果檔案中去。

8. 通過讀取結果檔案中的記錄指標來按序讀取記錄。想要優化這個操作,mysql將記錄指標讀取放到乙個大的塊裡,並且使用它來按序讀取記錄,將記錄放到緩衝中。緩衝的大小由系統變數read_rnd_buffer_size 的值而定。這個步驟的**在原始檔`sql/records.cc' 中。

這個逼近演算法的乙個問題是,資料庫讀取了2次記錄:一次是估算where 分句時,第二次是排序時。儘管第一次都成功讀取記錄了(例如,做了一次全表掃瞄),第二次是隨機的讀取(索引鍵已經排好序了,但是記錄並沒有)。在mysql 4.1 及更新版本中,filesort 優化演算法用於記錄中不只包括索引鍵值和記錄的位置,還包括查詢中要求的字段。這麼做避免了需要2次讀取記錄。改進的filesort 演算法做法大致如下:

1. 跟以前一樣,讀取匹配where 分句的記錄。

2. 相對於每個記錄,都記錄了乙個對應的;『元組』資訊資訊,包括索引鍵值、記錄位置、以及查詢中所需要的所有字段。

3. 根據索引鍵對『元組』資訊進行排序。

4. 按序讀取記錄,不過是從已經排序過的『元組』列表中讀取記錄,而非從資料表中再讀取一次。

使用改進後的filesort 演算法相比原來的,『元組』比『對』需要占用更長的空間,它們很少正好適合放在排序緩衝中(緩衝的大小是由sort_buffer_size 的值決定的)。因此,這就可能需要有更多的i/o操作,導致改進的演算法更慢。為了避免使之變慢,這種優化方法只用於排序『元組』中額外的字段的大小總和超過系統變數max_length_for_sort_data 的情況(這個變數的值設定太高的乙個表象就是高磁碟負載低cpu負載)。想要提高order by 的速度,首先要看mysql能否使用索引而非額外的排序過程。如果不能使用索引,可以試著遵循以下策略:

* 增加sort_buffer_size 的值。

* 增加read_rnd_buffer_size 的值。

* 修改tmpdir,讓它指向乙個有很多剩餘空間的專用檔案系統。

如果使用mysql 4.1或更新,這個選項允許有多個路徑用迴圈的格式。各個路徑之間在unix 上用冒號(':')分隔開來,在windows,netware以及os/2 上用分號(';')。可以利用這個特性將負載平均分攤給幾個目錄。注意:這些路徑必須是分布在不同物理磁碟上的目錄,而非在同乙個物理磁碟上的不同目錄

MySQL Order By索引優化

mysql order by索引優化 mysql可以直接使用索引來滿足乙個order by 子句而無需做額外的排序。儘管 order by 不是和索引的順序準確匹配,索引還是可以被用到。在一些情況下,mysql可以直接使用索引來滿足乙個 order by 或 group by 子句而無需做額外的排序...

mysql order by 排序索引

接手別人的 遇到乙個客戶需求,說介面查詢較慢,需要進行優化。後面通過列印執行時間定位到是某一句sql執行較慢。sql如下 select from t base alarm tba where1 1and tba.rule type 1order by alarm status asc end ts ...

MySQL Order By 使用索引的情況

最近看到有篇關於mysql order by的 文章 裡面有好幾點可疑的。原文 1 order by的索引優化。如果乙個sql語句形如 select column1 column2 from table order by sort 在 sort 這個欄位上建立索引就可以實現利用索引進行order b...