(十) 資料庫查詢處理之排序(sorting)

周小倫發表於2021-02-22

1. 為什麼我們需要對資料排序

  1. 可以支援對於重複元素的清除(支援DISTINCT)
  2. 可以支援GROUP BY 操作
  3. 對於關係運算中的一些運算能夠得到高效的實現

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+樹索引。那麼我們可以利用它進行優化。

這裡有兩種情況需要被考慮

  1. 聚簇索引

    資料的實體地址順序和索引的順序是一致的。

    這種方法比外部排序要好,因為它沒有額外的計算。比如不需要進行sort。不需要進行歸併。而且所有的磁碟訪問都是順序的。

  2. 非聚簇索引

    資料的實體地址順序和索引的順序是不一致的。

如果是這樣的索引。就利用外部排序就好。

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開始是因為現在正好看到這裡。而之前忘了整理了。會在後面所有的都看完之後進行整理的。

相關文章