天天看點

4個優化方法,讓你能了解join計算過程更透徹

摘要:現如今, 跨源計算的場景越來越多, 資料計算不再單純局限于單方,而可能來自不同的資料合作方進行聯合計算。

本文分享自華為雲社群《如何高可靠、高性能地優化join計算過程?4個優化讓你掌握其中的精髓》,作者: breakDraw 。

現如今, 跨源計算的場景越來越多, 資料計算不再單純局限于單方,而可能來自不同的資料合作方進行聯合計算。

聯合計算時,最關鍵的就是辨別對齊,即需要将兩方的角色将同一個辨別(例如身份證、注冊号等)用join操作關聯起來, 提取出兩邊的交集部分, 後面再進行計算,得到需要的結果。

而這種join過程看似簡單,其實有非常多的門道,這裡讓我從最簡單的join方法開始, 一步步示範join的優化過程。

首先假設以下場景:

有tb1, tb2兩張表的資料,存放在不同位置

各有相同的id列。

tb1有1億行資料,而tb2表隻有10w行資料。

拿到2張表的全量資料, 直接2個for循環進行周遊

如果id比對,則合并2個行記錄作為join結果

圖示如下:

4個優化方法,讓你能了解join計算過程更透徹

上面這種join有2個問題:

性能很差,兩次for循環相當于O(mn)的複雜度

為了收集全量資料, 可能導緻記憶體溢出,例如大表有10億行資料,無法一次性存放。

首先解決剛才提到的第一個問題

實際上join過程就很像一種命中過程, 是以可以聯想到哈希表。

我們使用一個 hashMap存儲較小的tb2表(隻有10w行)。

使用id列當作哈希表的key。

隻對大表做for循環,如果id列在哈希表中能比對中,則取出對用資料做拼接

這樣複雜度就優化到了O(m)了

還有一個問題沒解決: ”為了收集全量資料, 可能導緻記憶體溢出“。

那我們可以将大表按照特定數量進行拆分,分成多批資料

例如每次以1000條的數量,和小表進行上面的哈希表碰撞過程。這樣空間複雜度就是O (K + n)。

當每碰撞完一次,才接着接收下一批資料。如下面所示

4個優化方法,讓你能了解join計算過程更透徹

注意, ”告知計算完成這種響應機制“也可以優化成阻塞的緩沖隊列。

但是還有個問題, 如果小表本身也很大, 例如1億條, 計算節點連小表的哈希表都存不下,怎麼辦?

另外單節點計算的CPU有限,如何能在短時間内快速提升性能?

當計算節點存不下小表構成的哈希表時, 這時候可以擴容2個join計算節點, 引入分布式計算來分擔記憶體壓力。

例如我們可以對id列進行shuffle分片

id%3==0 分到計算節點A

id%3==1 分到計算節點B

id%3 ==2 分到計算階段C

如果id是均勻的, 則小表的資料就被拆成了3份,也許就能正好存下了。

大表資料按同樣的方式分片, 分到相同的節點, 對計算結果是沒有影響的, 隻要你的分片算法確定id比對的行一定在同一個節點即可。

4個優化方法,讓你能了解join計算過程更透徹

另外性能上, 分布式計算理論上按照節點數量也能夠提升N倍的join速度。

這種分布式計算的方式已經能解決大部分join作業了,但是還有個問題:

假設網絡帶寬壓力比較大(比如買的帶寬比較便宜,發送資料的成本比較大)

部分涉及安全的計算場景中可能需要對資料做加密

這2種情況都會造成資料在輸出時會耗費很多時間,甚至超過join的過程。那麼該如何優化?

本地計算,指的就是在通過網絡輸出資料前,先提前做一些預處理。這種操作在各種計算引擎中都有展現

在spark中有一個叫boardCast廣播資料的機制

presto中有一種叫runtimeFilter的方式。

對于join過程, 我們可以:

将小表的id進行一定的壓縮處理(例如哈希之後取前x位)

這樣可以減少傳輸的資料量。

然後将這塊資料傳輸給大表所在的節點, 進行提前的簡單join篩選, 這樣就可以提前過濾掉很多的沒必要通過網絡輸出的資料。

4個優化方法,讓你能了解join計算過程更透徹

以上僅僅隻是最基礎的join優化過程, 而在海量資料、高性能、高安全、跨網絡的複雜場景中, 關于join計算還會有更多的挑戰。

是以可以關注華為可信智能計算TICS服務,專注高性能高安全的聯邦計算和聯邦學習,推動跨機構資料的可信融合和協同,安全釋放資料價值。

點選關注,第一時間了解華為雲新鮮技術~

繼續閱讀