CMU Database Systems - Sorting,Aggregation,Join

Sorting

排序若是可在內存裏面排,用經典的排序算法就ok,好比快排算法

問題在於,數據表中的的數據是不少的,無法一下都放到內存裏面進行排序數據庫

因此就須要用到,外排,多路並歸排序函數

看下最簡單的,2路並歸排序,oop

設文件分爲N個page,memory中一次最多能夠放入B個pagesui

因此在sort過程,一次性能夠載入B個page,在內存中page內排序,寫回disk,稱爲一輪,run
那麼若是一共N個page,須要N/B+1個run設計

在merge過程,若是雙路並歸排序,只須要用到3個page的buffer,多了也沒用3d

Merge過程的costblog

每一個pass都須要讀寫一遍全部的數據,cost爲2N
2 way,因此一共有1 + logN個pass排序

多路並歸排序的通用公式以下,索引

其餘都比較容易理解,爲何way數是B-1?

由於memory一共B個buffer,須要留一個output,剩下的用於merge,因此最可能是B-1路並歸排序

 

若是咱們有B+ index的狀況下,

分兩種狀況,要排序的字段有Clustered B+索引,那麼直接從左到右遍歷葉子節點就好

排序的字段不是Clustered B+索引,好比是secondary 索引

那麼從索引裏面只能獲取到排好序的id,而後要經過id去Clustered B+索引中取真正的value,效率也很低,每一個record都須要一次io

 

Aggregation

Aggregation有兩種思路,

一種先排序sorting,而後再按順序作aggregate

這個方法明顯的問題,就是比較費,有些場景不須要sort,好比group by,distinct

因此第二種思路是Hashing,

在memory裏面臨時維護一個hash table,去重或聚合都在hash table上完成

問題就是,若是hash table太大,內存放不下怎麼辦?

因此解法的思路,放不下,就切開,切成能放下的一個個partition,而且要保證一個key的數據都在一個partition裏面,這樣只要保證內存可以放下一個partition就能夠aggregate,不須要去讀其餘的partition

這裏有幾個問題,

首先,一個partition應該不止一個key,若是隻有一個,第二步裏面的h2感受沒用
第二,假設數據是均勻分佈的,不會出現太大的傾斜,不會有partition overflow

 

Join

爲何須要join?

由於不一樣的數據存在不一樣的表裏面,因此要查詢就須要關聯
那麼爲何不能放在一張表裏面,關係表的設計有範式的要求,避免大量的數據重複

 

Join Operator Output

直接輸出data,這樣好處是,後續operator不用回到數據表再去讀數據
這個方法比較實用於TP需求,結果數據較少的狀況

僅僅輸出ids,適合AP需求,join結果集很是大的狀況

尤爲適用於列存,由於這樣你只須要讀出join id列,也不浪費

而後在最後要顯示的時候,纔去把須要的數據從表裏面查出來,這叫作late materialization

這樣的好處,過程當中可能還有其餘的join,過濾等,因此開始讀可能浪費,到最後真正須要的時候再讀

 

Join Cost

如何去評價join算法的好壞,就是要評價cost

傳統的數據庫的瓶頸在disk IO,因此這裏就以磁盤IO的次數來評價join算法的好壞,這個和爲什麼使用B+tree做爲index的理由同樣
因此就是讀寫page的個數

 

Join算法 

Nested Loop Join

Simple,直覺的方式就是遍歷兩個表
這裏的概念,分爲Outer和Inner表
從Cost上看,最要取決於Outer的tuples數,因此若是把較小的表N做爲Outer會效率高些  

比較明顯的問題是,沒有必要讀那麼多遍的inner表

若是我能把outer表直接放在內存中,那麼只須要讀一遍inner就能夠了,若是不行就用以下的block的方式

若是內存大小是B,那麼要用兩塊來放inner和output,因此能夠用B-2來放outer

Cost,outer表M須要讀一次,inner表須要讀M/(B-2)次

這裏也寫了,若是memory比較大,那麼cost就是M+N,只須要讀一遍inner

 

若是有index,是否能夠加快join的效率?應該能夠,可是效果要看是什麼index,若是hash,C=O(1),B+tree,C=O(logn)

 

Sort-Merge Join 

這個方法要求,兩個表先排序,而後作一輪幷歸就能夠完成join
因此這個方法適用於,兩個表自己就有序,或是在join key上有index
這個方法附帶的好處是結果有序

這個算法的Cost,主要是兩個表排序的cost,幷歸的cost就是M+N

 

Hash Join

HashJoin分爲兩步,兩步的hash函數用同一個

Build,對較小的表建臨時的hash table

Probe,讀取另外一張表,進行join

這有個相似的問題,Hash Table裏面存什麼?

固然能夠直接存join的結果,也能夠存tuple id,這個選擇就取決於場景

 

天然有個疑問,若是內存放不下這個hash table怎麼辦?

既然放不下,就須要分而治之,兩個表用相同的hash函數,hash到相同數目的buckets裏面去

在內存中,一次只讀一組bucket來進行join,是否是很ok

 

 那麼若是hash成bucket的時候,不均衡,一個bucket也overflow,怎麼辦?答案是繼續分

 

Grace Hash Join的cost

 

 全部join算法的Cost對比,

 

相關文章
相關標籤/搜索