資料蔣堂 JOIN提速 外來鍵指標化

2021-08-13 04:45:05 字數 1691 閱讀 1777

我們來看重新定義join後如何能夠提高運算效能,先看外來鍵式join的情況。

設有兩個表:

其中sales表中的productid是指向products表中id欄位的外來鍵,id是products表的主鍵。

現在我們想計算銷售額有多少(為簡化討論,就不再設定條件了),用sql寫出來:

select sum(sales.quantity*products.price) from sales join products on sales.productid=products.id

基於笛卡爾積定義的join,原則上只能兩層迴圈全遍歷來計算,不過這個計算量實在太大,關聯式資料庫一般採用hash分段方法優化,即分別計算兩表關聯欄位的hash值,將hash同值記錄拼到一起再做小範圍遍歷。網上有很多文章介紹這個演算法,這裡就不詳述了。這樣做後的複雜度能顯著降低,但仍然要做多次hash值計算和比對。

我有幾張阿里雲幸運券分享給你,用券購買或者公升級阿里雲相應產品會有特惠驚喜哦!把想要買的產品的幸運券都領走吧!快下手,馬上就要搶光了。

我們再用前述簡化的join語法寫出這個運算:

select sum(quantity*productid.price) from sales

而這個寫法其實也預示了它還可以有更好的優化方案,下面來看看怎樣實現。

我們先考慮全記憶體的情況,如果所有資料都能夠裝入記憶體,我們可以實現外來鍵指標化。

將事實表sales中的外來鍵字段productid,轉換成指向維表products記錄的指標,即productid的取值就已經是某個products表中的記錄,那麼就可以直接引用記錄的字段進行計算了。

用sql不方便描述這個運算的細節過程了,我們採用過程式語法、並用檔案作為資料來源來說明計算過程:

上面演算法中,第2步建主鍵索引一般也是用hash辦法,對id計算hash值,第4步轉換指標還是計算productid的hash值與p的hash索引表對比。這樣的話,如果只做一次關聯運算,指標化的方案和傳統hash分段方案的計算量基本上一樣,沒有根本優勢。

但不同的是,如果資料能在記憶體中放下,這個指標一旦建立起來之後可以復用,也就是說第2和第4步只要做一次,下次再做關於這兩個欄位的關聯運算時就不必再計算hash值和比對了,效能就能大幅提高。而關係代數體系下沒有物件指標這個概念,並且基於笛卡爾積定義的join運算也無法假定外來鍵指向記錄的唯一性,沒辦法使用外來鍵指標化的方法,每次關聯時都要計算hash值並比對。

而且,如果事實表中有多個外來鍵分別指向多個維表,傳統的hash分段join方案每次只能解析掉乙個,有n個join要執行n遍動作,每次關聯後都需要保持中間結果供下一輪使用,計算過程複雜得多,資料也會被遍歷多次。而外鍵指標化方案在面對多個外來鍵時,只要對事實表遍歷一次, 沒有中間結果,計算過程要清晰很多。

還有一點,記憶體本來應當是很適合平行計算的,但hash分段join演算法卻不容易並行。即使把資料分段平行計算hash值,但要把相同hash值的記錄歸聚到一起供下一輪比對,就會發生共享資源衝突的事情,這會把平行計算的優勢完全抵消掉。而外鍵式join模型下,關聯兩表的地位不對等,明確區分出維表和事實表後,只要簡單地將事實表分段就可以平行計算。

資料蔣堂 常規遍歷語法

遍歷可以說是最基本的集合運算了,比如求和 計數 尋找最大最小值等聚合運算,按條件過濾集合 根據集合成員生成另乙個新集合,也都是遍歷運算。集合化語法要求我們能用很短的語句 經常就只有一句,而不是若干語句構成的一段程式 來描述大部分遍歷運算,這樣我們需要考查遍歷運算中可能出現的各種常見情況,並設計出合理...

資料蔣堂 人工智慧中的「人工」

自從alphago贏了之後,人工智慧就變得非常熱門了。不過,大家在關注 智慧型 時,卻很少把注意力放在 人工 上,似乎感覺上了人工智慧之後,一切都能自動化了。其實,這份智慧型的背後有著大量的 人工 還有相當多不能自動化的事情。這裡的 人工 主要體現在兩個方面 1.資料準備 現代的人工智慧技術,或者說...

資料庫 外來鍵

外來鍵是什麼?外來鍵 fk 是用於建立和加強兩個表資料之間的鏈結的一列或多列。通過將儲存表中主鍵值的一列或多列新增到另乙個表中,可建立兩個表之間的鏈結。這個列就成為第二個表的外來鍵。外來鍵資料庫一級的完整性約束,由資料庫自行維護.你也可以手動建立.1如果存在外來鍵關係的話,任何修改主表主鍵欄位和刪除...