內容轉自搜狐古雷PPT
看mysql源碼的收穫
1.為最佳化提供理論依據
2.學習解決問題的演算法和思路
filesort algorithm(排序演算法)1.讀取所有需要排序的資料
2.每行資料
a.演算法1(original):儲存排序key和行指標
b.演算法2(modified):儲存排序key和select中的欄位
3.每次排序sort_buffer_size能容納的行數,排序結果寫入IO_CACHE對象(不妨稱為IO1),本次排序結果的位置資訊寫入另一個IO_CACHE對象(不妨稱為IO2);
4.IO_CACHE超過64k時寫入臨時檔案
5.當order by有limit n時,只需要把前n條排序結果寫入IO_CACHE;
6.排序KEY長度<=20且排序KEY數量在一千和十萬之間時使用radixsort,否則使用quicksort
7.Merge buffer
8.讀取排序結果(演算法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長度)
1.滿足下兩個條件之一時選擇original演算法
a.有text或者blob欄位
b.ength+sortlength > max_length_for_sort_data
3.否則選擇modified演算法
4.本例選擇了modified演算法
5.沒有text和blob欄位
6.length+sortlength=208
7.max_length_for_sort_data=1024
Sort buffer記憶體使用量1.keys= sort_buff_size/(rec_length+sizeof(char*))
2.rec_length=length+sortlength
本例中
a.rec_length=208
b.sizeof(char*)=4
c.sort_buff_size=2097116
d.keys=9892
即能在記憶體中一次排序的key為9892個
倒序的實現1.不是在比較KEY值大小時實現
a.發現正序、倒序,在比較KEY值大小的函數中沒有區別對待
b.差點以為把整個排序過程看錯了
2.是在向排序區寫入KEY值時實現
a.在跟蹤字元類型倒序倒序時
b.make_sortkey中對每個位元組取反
c.這樣後續的正序排序就相當於倒序排序
正序排序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,唯寫需要的欄位值。
Merge buffer主要原理各buffer自己的最小值,在一起再取最小值,就是所有buffer資料的最小值。
除去當前取得的最小值,再算當前buffer最小值的最小值,以此類推,得到排序的所有buffer資料。
用heapsort實現的mergesort。
為什麼用heapsort? 每次合并若干buffer時,不能拿到所有buffer的全部資料
對能取到sort buffer內的所有資料完全排序是沒意義的
以順序排序舉例,這些資料中,只有當前各buffer的最小值中的最小值能夠保證是所有buffer中最小的值,依次得到這個最小值,則得到完全排序的所有資料
heapsort也恰好是不完全排序,只保證root是最小的
營運上的思考計算一個SQL是否能在記憶體中完成排序
計算一個SQL使用哪種filesort演算法
Merge buffer的代價?
filesort舊演算法與新演算法資源消耗的評估?
最佳化的本質以小資源得大吞吐
高頻率用高效資源
低頻率使用低效資源
高效資源通常是相對稀缺的
協助實現最佳化目標的是演算法