MySQL資料庫Filesort過程
阿新 • • 發佈:2019-02-16
- 讀取所有需要排序的資料
- 每行資料
- 演算法1(original):儲存排序key和行指標
- 演算法2(modified):儲存排序key和select中的欄位
- 每次排序sort_buffer_size能容納的行數,排序結果寫入IO_CACHE物件(不妨稱為IO1),本次排序結果的位置資訊寫入另一個IO_CACHE物件(不妨稱為IO2);
- IO_CACHE超過64k時寫入臨時檔案
- 當order by有limit n時,只需要把前n條排序結果寫入IO_CACHE;
- 排序KEY長度<=20且排序KEY數量在一千和十萬之間時使用radixsort,否則使用quicksort
- Merge buffer
- 讀取排序結果(演算法2直接從臨時檔案讀取結果;演算法1從臨時檔案讀取行指標,再從表中讀取資料)
filesort algorithm選擇
select bgid from bigt order by bgname;
Create Table: CREATE TABLE `bigt` (
`bgid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`bgname` varchar(100) DEFAULT NULL,
`status` tinyint(4) DEFAULT ’0′,
PRIMARY KEY (`bgid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
bgid(4位元組)、bgname(102位元組)、(null_fields+7)/8=1
其中null_fields是1,bgname是可以為空的欄位
length=4+102+1=107
sort_length=101(bgname長度)
- 滿足下兩個條件之一時選擇original演算法
- 有text或者blob欄位
- length+sortlength > max_length_for_sort_data
- 否則選擇modified演算法
- 本例選擇了modified演算法
- 沒有text和blob欄位
- length+sortlength=208
- max_length_for_sort_data=1024
Sort buffer記憶體使用
- keys= sort_buff_size/(rec_length+sizeof(char*))
- rec_length=length+sortlength
- 本例中
- rec_length=208
- sizeof(char*)=4
- sort_buff_size=2097116
- keys=9892
- 即能在記憶體中一次排序的key為9892個
倒序的實現
- 不是在比較KEY值大小時實現
- 發現正序、倒序,在比較KEY值大小的函式中沒有區別對待
- 差點以為把整個排序過程看錯了
- 是在向排序區寫入KEY值時實現
- 在跟蹤字元型別倒序倒序時
- make_sortkey中對每個位元組取反
- 這樣後續的正序排序就相當於倒序排序
正序排序Merge buffer示例
- 實際mysql原始碼中是每7個buffer進行合併
- 本例做了簡化,只對5個buffer進行合併
- 所謂buffer是一次排序結果,儲存在臨時檔案(IO_CACHE)中
- 5個buffer就是臨時檔案中的五個段,每段儲存一次排序的結果
- Merge buffer的演算法是heapsort實現的mergesort
- 首先每個段取第一個排序key,加入heap
- 加入時保證heap的排序