1. 為什麼我們需要對資料排序
- 可以支援對於重複元素的清除(支援DISTINCT)
- 可以支援GROUP BY 操作
- 對於關係運算中的一些運算能夠得到高效的實現
2. 引入外部排序演算法
對於不能全部放在記憶體中的關係的排序。就需要引入外排序,其中最常用的技術就是外部歸併排序。
外部排序分為兩個階段
Phase1 - Sorting
對主存中的資料塊進行排序,然後將排序後的資料塊寫回磁碟。
Phase2 - Merging
將已排序的子檔案合併成一個較大的檔案
2.1 N-way 外部歸併排序
從2路歸併排序開始。來引出N路歸併排序演算法
可以見下圖
對於簡單的二路歸併。我們有兩個buffer可以用。一個用來放輸入進行排序得到歸併塊。而另一個則用來放輸出
下面來分析一下二路歸併的時間複雜度
在每一個階段我們都需要把歸併塊從磁碟中讀入。然後在寫回磁碟因此總共的I/O次數就是階段數 * 2
階段數可以很容易的得到為
可以很容易的發現上面的問題主要出現在。由於我們的輸入緩衝區只能放一個page。所以這導致了我們不停的進行換入換出導致了io次數變得非常多。優化方法就是加大緩衝區大小。減少階段數。這就需要我們歸併路數增大。
使用B buffer pages 這樣我們的輸入緩衝區就可以放B - 1個page。這樣我們的階段數就可以減少了。
2.2 利用索引進行加速
如果我們的table中已經有了B+樹索引。那麼我們可以利用它進行優化。
這裡有兩種情況需要被考慮
-
聚簇索引
資料的實體地址順序和索引的順序是一致的。
這種方法比外部排序要好,因為它沒有額外的計算。比如不需要進行sort。不需要進行歸併。而且所有的磁碟訪問都是順序的。
-
非聚簇索引
資料的實體地址順序和索引的順序是不一致的。
如果是這樣的索引。就利用外部排序就好。
2.3 AGGREGATIONS
將多個元組摺疊為單個標量值。有兩種實現方法
1. 排序
排序之後相同的元素就會在排在一起。這樣就可以去除冗餘元素
2. hash
但是如果我們不要求資料是有序的。這樣我們排序就相當於浪費了時間。因為排序起碼要花費nlogn的時間。比如GROUP BY
和DISTINCT
操作。在這種情況下。hashing就是一個更好的選擇
1. Partition
假設我們有B buffers。其中B - 1個buffer用來partitions而1個buffer用來儲存輸出data。
第一階段就是利用一個hash函式。把tuple雜湊到不同的桶中。
2. Rehash
由於階段1之後。擁有相同cid值的tuple都被對映到了相同的桶內。這個階段我們對不同的桶在進行一次hash。就可以完成我們的去重操作。
當然利用hash操作不僅可以進行去重還可以進行其他的操作。如MAX、MIN、AVG、COUNT、SUM等
下面這張圖演示了count操作和sum操作。
這張圖演示了avg操作就是利用 sum / count
這個算是結合cmu15-445課程和對應的教材、ppt進行的總結。順序從10開始是因為現在正好看到這裡。而之前忘了整理了。會在後面所有的都看完之後進行整理的。