摘要:現如今, 跨源計算的場景越來越多, 資料計算不再單純局限于單方,而可能來自不同的資料合作方進行聯合計算。
本文分享自華為雲社群《如何高可靠、高性能地優化join計算過程?4個優化讓你掌握其中的精髓》,作者: breakDraw 。
現如今, 跨源計算的場景越來越多, 資料計算不再單純局限于單方,而可能來自不同的資料合作方進行聯合計算。
聯合計算時,最關鍵的就是辨別對齊,即需要将兩方的角色将同一個辨別(例如身份證、注冊号等)用join操作關聯起來, 提取出兩邊的交集部分, 後面再進行計算,得到需要的結果。
而這種join過程看似簡單,其實有非常多的門道,這裡讓我從最簡單的join方法開始, 一步步示範join的優化過程。
首先假設以下場景:
有tb1, tb2兩張表的資料,存放在不同位置
各有相同的id列。
tb1有1億行資料,而tb2表隻有10w行資料。
拿到2張表的全量資料, 直接2個for循環進行周遊
如果id比對,則合并2個行記錄作為join結果
圖示如下:

上面這種join有2個問題:
性能很差,兩次for循環相當于O(mn)的複雜度
為了收集全量資料, 可能導緻記憶體溢出,例如大表有10億行資料,無法一次性存放。
首先解決剛才提到的第一個問題
實際上join過程就很像一種命中過程, 是以可以聯想到哈希表。
我們使用一個 hashMap存儲較小的tb2表(隻有10w行)。
使用id列當作哈希表的key。
隻對大表做for循環,如果id列在哈希表中能比對中,則取出對用資料做拼接
這樣複雜度就優化到了O(m)了
還有一個問題沒解決: ”為了收集全量資料, 可能導緻記憶體溢出“。
那我們可以将大表按照特定數量進行拆分,分成多批資料
例如每次以1000條的數量,和小表進行上面的哈希表碰撞過程。這樣空間複雜度就是O (K + n)。
當每碰撞完一次,才接着接收下一批資料。如下面所示
注意, ”告知計算完成這種響應機制“也可以優化成阻塞的緩沖隊列。
但是還有個問題, 如果小表本身也很大, 例如1億條, 計算節點連小表的哈希表都存不下,怎麼辦?
另外單節點計算的CPU有限,如何能在短時間内快速提升性能?
當計算節點存不下小表構成的哈希表時, 這時候可以擴容2個join計算節點, 引入分布式計算來分擔記憶體壓力。
例如我們可以對id列進行shuffle分片
id%3==0 分到計算節點A
id%3==1 分到計算節點B
id%3 ==2 分到計算階段C
如果id是均勻的, 則小表的資料就被拆成了3份,也許就能正好存下了。
大表資料按同樣的方式分片, 分到相同的節點, 對計算結果是沒有影響的, 隻要你的分片算法確定id比對的行一定在同一個節點即可。
另外性能上, 分布式計算理論上按照節點數量也能夠提升N倍的join速度。
這種分布式計算的方式已經能解決大部分join作業了,但是還有個問題:
假設網絡帶寬壓力比較大(比如買的帶寬比較便宜,發送資料的成本比較大)
部分涉及安全的計算場景中可能需要對資料做加密
這2種情況都會造成資料在輸出時會耗費很多時間,甚至超過join的過程。那麼該如何優化?
本地計算,指的就是在通過網絡輸出資料前,先提前做一些預處理。這種操作在各種計算引擎中都有展現
在spark中有一個叫boardCast廣播資料的機制
presto中有一種叫runtimeFilter的方式。
對于join過程, 我們可以:
将小表的id進行一定的壓縮處理(例如哈希之後取前x位)
這樣可以減少傳輸的資料量。
然後将這塊資料傳輸給大表所在的節點, 進行提前的簡單join篩選, 這樣就可以提前過濾掉很多的沒必要通過網絡輸出的資料。
以上僅僅隻是最基礎的join優化過程, 而在海量資料、高性能、高安全、跨網絡的複雜場景中, 關于join計算還會有更多的挑戰。
是以可以關注華為可信智能計算TICS服務,專注高性能高安全的聯邦計算和聯邦學習,推動跨機構資料的可信融合和協同,安全釋放資料價值。
點選關注,第一時間了解華為雲新鮮技術~