MySQL Order By索引優化

2021-06-03 04:47:32 字數 3067 閱讀 2504

mysql order by索引優化

mysql可以直接使用索引來滿足乙個order by 子句而無需做額外的排序。儘管 order by 不是和索引的順序準確匹配,索引還是可以被用到。

在一些情況下,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 排序索引

接手別人的 遇到乙個客戶需求,說介面查詢較慢,需要進行優化。後面通過列印執行時間定位到是某一句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 或group by 子句而無需做額外的排序。儘管order by 不是和索引的順序準確匹配,索引還是可以被用到,只要不用的索引部分和所有的額外的order by 欄位在where 子句中都被包括了。使用索引的mysql order ...

MySQL Order By 使用索引的情況

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