一般的join如果兩邊的join條件是一一對應是性能比較好的情況士葫,但是當遇到j(luò)oin條件兩邊存在多行對應一行或者多行對應多行的情況乞而。就會出現(xiàn)M行join N行? ?結(jié)果就會產(chǎn)生笛卡爾積M*N行。如果M和N都不大還好慢显。通過shuffle到磁盤一樣能計算出來爪模。但是如果M和N都很大而且不止兩表,有很多表同時join鳍怨。那么將會出現(xiàn)final stage之前將shuffle write M*N*K*P...? 無限擴張的數(shù)據(jù)集呻右。而且根本沒法優(yōu)化。
如下DAG:
本來只有百萬級別的數(shù)據(jù)量鞋喇,經(jīng)過cross join后 數(shù)據(jù)量達到百億千億級別声滥。將耗費大量時間去shuffle write,也會導致大量executor磁盤消耗侦香。
剛開始可能會想如果將左表進行collect操作? 先減少主表的數(shù)據(jù)量就會減少整個DAG的數(shù)據(jù)量落塑。但是collect之后只能在map/foreach函數(shù)進行接下來的操作。就會導致整個DAG產(chǎn)生大量的小job罐韩,能算了 但是特別慢而且不優(yōu)雅憾赁。
因為經(jīng)過join多表才產(chǎn)生的cross join,那么不妨把多表進行單獨的倆表join散吵,就算產(chǎn)生cross join 數(shù)據(jù)量也是可控的龙考。
但是spark的DAG是根據(jù)整體算子構(gòu)建最后的action算子才會觸發(fā)計算,那么無論何種方式進行DAG構(gòu)建矾睦,最終還是會匯總到一起再計算晦款。還是會產(chǎn)生多表cross join。
那么問題就來到如何提前觸發(fā)倆表join的提前計算了枚冗。
眾所周知repartition可以觸發(fā)shuffle缓溅,但是shuffle只是改變分區(qū)數(shù),shuffle=提前計算嗎赁温?
于是我就試了一試坛怪。果然淤齐。。袜匿。
repartition觸發(fā)了shuffle更啄,相當于觸發(fā)了提前計算。大大減少了數(shù)據(jù)量 而且最后還能以對等join進行連接沉帮。