天天看點

MySQL進階 之 order by、group by 優化order by示例FileSort排序算法group by 示例

order by示例

示例資料:

MySQL進階 之 order by、group by 優化order by示例FileSort排序算法group by 示例

Case 1

MySQL進階 之 order by、group by 優化order by示例FileSort排序算法group by 示例

Case 2

MySQL進階 之 order by、group by 優化order by示例FileSort排序算法group by 示例

Case 3

MySQL進階 之 order by、group by 優化order by示例FileSort排序算法group by 示例

Case 4

MySQL進階 之 order by、group by 優化order by示例FileSort排序算法group by 示例

結論:order by子句,盡量使用Index方式排序,在索引列上遵循索引的最佳左字首原則。

複合(聯合)索引形如 key (‘A1’,’A2’,’A3’ ),排序的思路一般是,先按照A1來排序,A1相同,然後按照A2排序,以此類推,這樣對于(A1),(A1,A2), (A1,A2,A3)的索引都是有效的,但是對于(A2,A3)這樣的索引就無效了。盡量避免因索引字段的缺失 或 索引字段順序的不同 引起的FileSort排序。

order by 總結

MySQL進階 之 order by、group by 優化order by示例FileSort排序算法group by 示例

FileSort排序算法

算法一:雙路排序算法

隻利用ORDERBY子句中包括的列對象進行排序(适用于有BLOB、TEXT類型的列對象參與的排序)

MySQL4.1之前的排序算法,完整實作過程如下:

1) 按索引鍵或全表掃描的方式,讀取所有的元組,不比對WHERE子句的元組被跳過;第一步需要從存儲讀入資料,引發I/O操作。

2) 對于每一行,在緩沖區中存儲一對值(對值,包括排序關鍵字和元組指針)。緩沖區的大小是系統變量的sort_buffer_size設定的值。

3) 當緩沖區已滿,運作快排算法(快速排序,qsort)對一個塊中的資料進行排序,将結果存儲在一個臨時檔案。儲存一個指向排序後的塊的指針(如果第二步所說的對值都能被緩沖區容納,則不會建立臨時檔案)。

4) 重複上述步驟,直到所有的行已經被讀取。

5) 執行一個多路歸并操作(操作對象是第三步生成的每一個有序的塊)彙集到“MERGEBUFF域”,然後存放到在第二個臨時檔案中。重複操作,直到第一個檔案的所有塊歸并後存入到第二個檔案;“MERGEBUFF域”是代碼sql_sort.h中定義的宏,值為7。

6) 重複以下操作(第7步和第8步),直到留下少于“MERGEBUFF2域”标明的塊數為止;“MERGEBUFF2域”是代碼sql_sort.h中定義的宏,值為15。

7) 在最後一次多路歸并操作中,把元組的指針(排序關鍵字的最後部分)寫入到一個結果檔案。

8) 在結果檔案中,按照排列的順序使用元組指針讀取元組(為了優化這項操作,MySQL讀入元組指針進入一個大的塊,對塊中元組指針進行排序而不是直接對資料排序,然後再用有序的元組指針擷取元組到元組緩存,元組緩沖區的大小由read_rnd_buffer_size參數控制)。第8步需要從存儲讀入資料,引發I/O操作。

算法二:單路排序算法

除利用ORDERBY子句中包括的列對象外,還利用查詢目标列中的所有列對象進行排序(适用于除BLOB、TEXT類型外的所有的其他類型的排序)

MySQL4.1之後出現的改進算法,減少一次I/O,需要增加緩沖區大小容納更多資訊。其具體實作過程如下:

1) 擷取與WHERE子句比對的元組。這一步需要從存儲讀入資料,引發I/O操作。

2) 對于每一個元組,記錄排序鍵值、行的位置值、查詢所需的列。這一步記錄更多内容,需要更大緩存,記憶體存儲一條元組的資訊的長度比算法一的“對值”大許多,這可能引發排序速度問題(排序對象的長度變長,但是記憶體有限,是以就需把一次記憶體排序變為多次,進而影響排序的速度),為了控制這個問題,MySQL引入一個參數“max_length_for_sort_data”,如果這一步得到的元組長度大于這個值,則不使用算法二。需要MySQL的使用者特别注意的是,在排序中,如果存在“很高磁盤I/O和很低的CPU使用率”的現象,則需要考慮調整“max_length_for_sort_data”的大小以變更換排序算法。

3) 按照排序的鍵值,對元組(元組是第二步的結果)進行排序。

算法二直接從緩沖區中的排序的元組中擷取有序的列資訊等(查詢的目的對象),而不是第二次通路該表讀取所需的列。相比算法一減少一次I/O。

FileSort優化政策

當無法使用索引列排序時,為了提高Order By的速度,應該嘗試一下優化:

1、避免使用 “select * ” 。查詢的字段越多導緻元組長度總合可能

超過max_length_for_sort_data的設定,導緻無法使用單路排序算法,隻能用雙路排序算法。

超過sort_buffer_size的設定,超出後會建立tmp檔案進行合并,導緻多次IO

2、适當增大sort_buffer_size參數的設定

3、适當增大max_length_for_sort_data參數的設定

group by 示例

示例:

MySQL進階 之 order by、group by 優化order by示例FileSort排序算法group by 示例
MySQL進階 之 order by、group by 優化order by示例FileSort排序算法group by 示例

group by 總結

group by與order by的索引優化基本一樣,group by實質是先排序後分組,也就是分組之前必排序,遵照索引的最佳左字首原則可以大大提高group by的效率。

當無法使用索引列排序時,适當增大sort_buffer_size參數 + 适當增大max_length_for_sort_data參數可以提高filesort排序的效率。注意:可能會出現Using temporary,也就是說mysql在對查詢結果排序時使用了臨時表。

where高于having,能寫在where限定條件中的就盡量寫在where中。

繼續閱讀