Hiveのjoinの最適化

元ネタはこちら
Join Optimization in Apache Hive

Hiveは0.7からjoinが最適化されています。どのように最適化されたのか上記の資料をひもといてみます。


いままでのjoin

いままでのjoinはいわゆるソートマージジョインです。
mapフェーズでテーブルのデータを読み込んでjoinキー、joinバリューを出力し、shuffleフェーズでソート、reduceフェーズでjoinという流れです。
この場合shuffleフェーズのソート処理がボトルネックとなっていました。

そこで登場するのがMap Joinです。
joinの片方のテーブルのサイズがメモリに収まるほど小さいのであれば、mapperのメモリに読み込んでmapフェーズだけでjoinします。

こんな感じの構文で書きます。

select /*+mapjoin(a)*/ * from src1 x join src2 y on x.key=y.key;

しかし数千ものmapperがあるような場合ではHDFSからメモリにデータを持ってくる部分がボトルネックとなりスケールしません。

そこで分散キャッシュを使います。

分散キャッシュの使用

Map Joinを行う前にローカルで実行するMapReduceタスクを用意し、そこでHDFSからメモリにテーブルのデータを持ってきて分散キャッシュにアップロードします。

これで解決ですね。

テーブルのサイズが小さければMap Joinを使い、そうでなければ普通のJoinを使えばいいわけですが、
わざわざ

select /*+mapjoin(a)*/ * from src1 x join src2 y on x.key=y.key;

とユーザに書かせるのは間違いの元です。

そこでデータのサイズに応じて自動判定するようにします。

データのサイズに応じてjoinをMap Joinに変換

どのくらいデータが小さければMap Joinを使うかの判定にはhive.smalltable.filesizeプロパティを使います。デフォルトは25MBです。

以上の最適化により下記のように性能が向上しました。

Map Joinの場合は12-26倍の性能向上です。

普通のjoinの場合は 57% - 163% の性能向上です。


下記はその他の参考資料です。

プレゼン資料

上記に加えてBucket Map Join, Bucket Sort Merge Map Join, Skew Joinもプラスした資料

https://cwiki.apache.org/confluence/download/attachments/27362054/Hive+Summit+2011-join.pdf?version=1&modificationDate=1310001042000

その資料をプレゼンした動画