1. 程式人生 > >MySQL資料庫Filesort過程

MySQL資料庫Filesort過程

  • 讀取所有需要排序的資料
  • 每行資料
  •     演算法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從臨時檔案讀取行指標,再從表中讀取資料)


merge buffer

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的排序

Merge buffer總結

•MySQL原始碼中,周而復始進行合併 •每次合併7個buffer,直到全部合併 •合併時仍然使用sort buffer記憶體 •最後一次合併時不再向排序結果中寫入排序KEY,只寫需要的欄位值 •各buffer自己的最小值,在一起再取最小值,就是所有buffer資料的最小值 •除去當前取得的最小值,再算當前buffer最小值的最小值,以此類推,得到排序的所有buffer資料 •用heapsort實現的mergesort

為什麼用heapsort?

• 每次合併若干buffer時,不能拿到所有buffer的全部資料 •對能取到sort buffer內的所有資料完全排序是沒意義的 •以順序排序舉例,這些資料中,只有當前各buffer的最小值中的最小值能夠保證是所有buffer中最小的值,依次得到這個最小值,則得到完全排序的所有資料 •heapsort也恰好是不完全排序,只保證root是最小的

運維上的思考

•計算一個SQL是否能在記憶體中完成排序 •計算一個SQL使用哪種filesort演算法 •Merge buffer的代價? •filesort舊演算法與新演算法資源消耗的評估?