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もプラスした資料
その資料をプレゼンした動画