Hive LLAP解説 | Hadoop Advent Calendar 2016 #09

こんにちは、小澤です。 この記事はHadoop Advent Calendar 9日目のものとなります。

前回はHiveを実用的に利用する上での様々な機能について紹介しました。
今回はHive2.0から新機能であるLLAPについて書かせていただきます。

OLAPとしてHive

HiveなどのSQL on Hadoopの登場によってDWHのような用途でHadoopを使うという需要が出てきました。 実際ImpalaのようなHiveQLをそのまま記述できるMPPも登場しています。

こういった用途の場合、何度も試行錯誤を繰り返しながらデータを抽出するため、素早く結果を返すことが求められます。 しかしながら、Hadoop上で動くことが前提となるHiveの場合、そもそもがバッチ処理を想定していたこともあり大規模なデータは扱えるがレイテンシには難ありといった使い方しか今まではできませんでした。

もちろん、現在では実行エンジンとしてTezやSparkが使えたり、ParquetやORCのようなカラムナ型のファイルを利用するなど高速化のための仕組みは多く存在していますが、それでも数秒から数十秒といったところが限界です。

LLAPはHadoop上で動作させながらもこの限界を超えるための仕組みとして登場しました。

高速化のための仕組み

それでは、LLAPがどのようにさらなる高速化を実現しているのか見ていきましょう。

コンテナのデーモン化

Hadoopはジョブが実行された際に初めてコンテナを起動させます。 大規模なデータをバッチ処理する場合は全体としての処理時間が長いため、この起動にかかる時間は無視できる程度のわずかなものでした。

一方で処理に時間がかからない場合はこの起動コストが処理全体の大半を占めるという状況にもなりえます。 例えば、コンテナの起動に1秒以上かかるとしたら、処理にかかる時間がミリ秒の単位であっても絶対に1秒以下にはなりえません。

そこでLLAPではあらかじめHadoop上でデーモンとして起動させておいたコンテナを利用します。

Hive on Tezの環境では構文解析されたHiveQLからTezのDAGを生成します。 この際、一部の処理をあらかじめ起動させておいたコンテナで処理させようというのがLLAPの発想です。

llap1

LLAPはジョブ全体の一部のみの利用も可能ですし、全体を通してデーモンを使うこと可能です。

スレッド

LLAPデーモンの中では複数のスレッドが起動しており、スレッドの数を適切に指定することでハードウェアのCPUなどのリソースも効率よく利用することが可能になっています。 また、処理を行うスレッドとIO用のスレッドが分かれており、非同期にデータの取得をおこなうことでのリソース活用の効率化も行われています。

Hiveでの実際の処理はDAG上の個々のノードで行う処理であるQuery Flagmentというものに分解されています。 LLAPデーモンではこのQuery FlagmentをQueueに貯め順次実行されていくとともに、極端に遅い処理を中断し優先度の高いものを先に実行するPreemption機能も実装されています。

llap2

キャッシュ

LLAPはデーモンの内部でキャッシュを持っています。このキャッシュは列(正確にはさらにその中で細かい単位)で持っており、頻繁にアクセスされるデータは入力も含めてディスクIOが発生することなくメモリ内で処理が完了します。 そのため、通常のHadoopの処理と違い、ウォームアップしておくことで速度が向上するというのも特長です。

現状のLLAPのキャッシュ機能はORCというファイルフォーマットに依存しています。 これは、列単位でデータを保持しているのとその中でのどの範囲の行を保持しておくかを判断するのに必要な情報を持っていることによります。

LLAPの役割ではないこと

LLAPはこういう目的ではないという点についてもいくつか挙げておきます。

まず第一にLLAPは実行エンジンではありません。 Hiveの実行エンジンはMapReduce, Tez, SparkとありますがLLAPがこれに並ぶものではありません。 これらの一部(または全部)をデーモン上で実行させる仕組みを提供するものになります。

次にLLAPはストレージでもありません。 それ自体にHadoopが実現しているような堅牢性があるわけでもなく、あくまでもデーモン上で保持しているキャッシュという位置付けです。 そのためデータの実態はHDFSなどに保持されていることが前提となります。

LLAPとバッチ処理

LLAPは位置付けとして、MapReduceに対するTezのようなより優れた仕組みを提供するというより適材適所で使い分けるものと考えたほうがいいかと思います。

デーモンを起動するということはそれだけHadoopクラスタ上のリソースを常に占有するということです。 そのため、他の処理も同じクラスタ上で実行したいときなどに影響がでるか、そのためにノードの追加などが必要になる可能性も考えられます。

また、デイリーのバッチ処理といったような実行頻度が高いわけではなく、データも毎回入れ替わるためキャッシュも効きづらく、レイテンシを気にするような状況でなければあえて使う理由もないかと思います。

終わりに

今回はHiveのLLAPという機能について紹介しました。 HiveはHadoopのエコシステムの中でも古株で、後発のものに比べるとレガシーに見える側面もある一方で今での人気のシステムです。 LLAPがそうであるようにHadoopのエコシステム界隈も適材適所で必要なものを使い分ける能力も今後必要になってくるかもしれませんね。

明日はHiveで動きSQLで記述できる機械学習のライブラリであるHivemallについて書かせていただく予定です。
ぜひ、お楽しみに!