Mysql中的雙路排序和單路排序

just1t發表於2024-05-08

在Mysql中使用orderby進行排序的時候,是可以使用到索引排序的,但是需要新增一些限制條件,例如:
select * from t_user where name='張三' order by name;使用這種方式就可以使用到索引,同時使用limit也是可以使用到索引的
select * from t_user order by name;透過這種方式不會使用到索引

什麼時候出現索引排序,什麼時候出現檔案排序:

  • 索引排序:當Mysql能夠使用索引來執行查詢並且可以利用索引中的資訊來實現排序的時候,叫索引排序
  • 檔案排序:當Mysql不能透過索引中的資料實現排序,叫檔案排序

Mysql中的索引排序的流程:
select id,price from likes where price=199 order by price; sql 1
select id,name,price from likes where price =199 order by price; sql 2
這裡存在兩種情況,一種是存在覆蓋索引的情況,如果存在覆蓋索引(sql 1)就會透過索引進行排序之後直接返回,第二種情況是需要進行回表查詢的情況(sql 2),需要先透過索引進行排序,排序完成之後透過id回表查詢我們需要的資料。

我們要儘量使用索引排序,如果沒有使用索引排序,mysql就是使用檔案排序(filesort)
檔案排序有兩種:

  • 雙路排序(回表排序模式):在執行的時候,會先根據條件將排序欄位和主鍵id(定位行資料的欄位)進行取出,然後放到sortbuff中(執行排序時分配的記憶體)進行排序,在排序完成之後需要透過主鍵id回表查詢出其他我們需要的資料。
  • 單路排序:在執行的時候,會將我們需要的資料都載入到sortbuff中進行排序,排序完成之後,直接將記憶體中的資料直接返回,不需要在進行回表查詢。

這裡舉一個例子:
select id,name,price from likes order by price;,我們在price列中建立了索引,但是因為沒有條件限制,我們還是會走filesort的

當使用單路排序的時候:
這裡我們需要的資料是 id、name、price,所以他就會將對應的這三列的資料放到sortbuff中,透過對price欄位進行排序,排序完成之後,直接就將資料進行返回了。

當使用雙路排序的時候:
儘管我們需要id、name、price,在排序的時候,也只會將id(定位行資料的欄位,建立聚簇索引的欄位),price欄位(透過該欄位進行排序)載入到sortbuff中,透過對price欄位進行排序,排序完成之後,會將排序結果集中的id進行回表查詢(因為我們還需要name欄位),查詢出我們需要的資料,在進行返回

雙路排序和單路排序的優缺點:

  • 雙路排序:因為雙路排序需要繼續兩次訪問資料,所以效率較慢
  • 單路排序:單路排序只需要訪問資料一次就行了,所以效率較高,但是因為單路排序是將我們需要的資料都儲存在記憶體中,所以可能會佔用更多的記憶體。

注意下:當sortbuff不足的時候,mysql會使用磁碟用來輔助排序,這種情況在雙路排序和單路排序中都可能發生,那是不是單路排序出現這種情況的次數會更多呢?其實不然,單路排序通常不會出現這種情況,為什麼呢,這需要了解什麼時候使用單路排序,什麼時候使用雙路排序。

雙路排序和單路排序如何選擇的:

在排序的時候,會首先判斷是索引排序還是檔案排序,如果是索引排序,就透過索引排序進行,如果是檔案排序,首先需要判斷我們需要的欄位(例如上述例子中的id、name、price)的總大小是否超過max_length_for_srot_data,如果超過了就會使用雙路排序,如果沒有超過就會使用單路排序。

相關文章