Hadoop関連の用語をざっくりまとめる【Hive, Presto, Spark】

## はじめに
この記事はビッグデータで用いる分散処理関連の用語について初学者向けにまとめたものです。
ある程度詳しい人にとっては退屈な内容かもしれないです。
**Hadoop、Hive、Spark、Presto、Mapreduce...**ビッグデータ周りはこういった用語が多いです。
自分は初めてこれらに触れたときに訳がわからなくて泣きそうになったのでざっくりとまとめました。
各々の説明はそんなに詳しくはしないので、イメージを掴むくらいを目的としています。

## ビッグデータと分散処理
最近**ビッグデータ**って言葉よく聞きますね。
対になる用語として**スモールデータ**ってものあります。
文字通りビッグデータとは容量がクソでかいデータのことなのですが、明確な定義はなく、だいたい数百万レコードまでならスモールデータって呼ばれるみたいです。（数GBくらい）
**そもそもなぜビッグデータ処理なるものを考えなければいけないのだろう？**
例えばデータベースに保存したデータを取り出したい時「MySQLなどを用いてRDBからSQL文でデータを取り出す」などの処理が考えられますね。
データが小さければ一台のPCにすべてのデータを保存してそこからデータを取り出せば良いわけですが、データの容量が大きくなるとだんだんそれが難しくなります。
そのためビッグデータを扱う場合は複数に**分散させて保存**する必要があるわけです。
問題は保存だけではありません。
通常のMySQLなどの仕組みだと集計時間がめちゃくちゃかかるので、データをどういった形式で保存しどういった**計算リソースを使って並列処理**するかも大事になってきます。
さらにこれをどうやって取り出すかも重要です。このように複雑な分散処理を経たものを**SQLのように出来るだけ簡単に、直感的に取り出す**にはどうすれば良いか。
これを解決するために近年よく用いられている分散処理フレームワークが**Hadoop (Apache Hadoop)**です。


## Hadoopとは
Wikipediaから引用すると「大規模データの分散処理を支えるオープンソースのソフトウェアフレームワーク」とあります。
つまり分散処理のフレームワークなわけですが、単一ではなくいくつかのソフトウェアから成りたっています。
以下に概念図を貼っておきます。（引用元：https://sungsoo.github.io/2014/04/27/comparing-apache-spark-and-apache-tez.html）

<img width="650" alt="![スクリーンショット 2020-06-21 16.34.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547532/7d9bec3d-0257-747b-410a-eabb5e287594.png">

ちなみに左端にあるゾウさんはHadoopのロゴです。可愛いかどうかと聞かれると、うーん...という見た目ですね。
Hadoopは図のように分散ファイルシステムである**HDFS**、その上に計算リソースを管理する**YARN**があり、分散データ処理は**MapReduce**や**Tez**などで行います。


### HDFS
HadoopにおいてはデータはHDFS (Hadoop Distributed File System) に保存されます。
名前の通り一箇所ではなく複数の箇所に分散して保存されるってことです。
とはいえ大規模データを複数箇所に保存しているため「エラーが発生して一部のデータが読み出せない」といった現象が起きる可能性があります。
こういった問題に対処するため同じデータを複数箇所にコピーすることでいい感じに冗長性を保っています。


### YARN
HDFSに保存されたデータから分散処理をするわけですが、どの計算リソースにどれくらいのCPU、メモリを割り振るかを管理するのが**YARN**です。
計算リソースをコンテナと呼ばれる単位で管理しています。
YARNは計算を効率よく行われるために、HDFSと連動して出来るだけデータの近くで計算を実行したりしてくれてます。
なお、ここでいうコンテナはDockerなどで出てくるコンテナ（OSレベルの仮想化）とは別物で、単に「どの計算をどのCPUとこのメモリで計算するか」といったアプリケーションレベルの枠組みみたいです。
また、YARNとは別にOSレベルでコンテナ化した上で計算リソースを割り振ってくれる**Mesos**というやつもいます。
こうやって聞くとMesosのほうが強そうですが、YARNと違ってHDFSと連携して効率よく計算したりしてくれないので、YARNの方がビッグデータの分散処理には適しているっぽいです。

### MapReduce
Goodleから2004年に出された論文がベースになっています。
**Map**と**Reduce**がセットになっており、Map並列処理をして、Reduceで統合する、という流れを繰り返します。
例えばSUMを計算する場合は複数のMapそれぞれで和の計算を並列して行い、Reduceでそれぞれの結果を統合します。
こうすることで効率的に計算の並列化を行うことができる。
ただし、**Map**と**Reduce**を必ずセットで行わなければいけないことや、Reduceの結果を**一旦ディスクに書き出してから次のMapに移らなければならない**など、コスパが悪く時間がかかりがちなので、現在では純粋はMapReduceあまり使われない。
これらの無駄な処理を無くして高速化したものとして**Tez**があり、こちらのほうがよく使う。
**Tez**は**MapReduce**の上位互換なイメージなので、とりあえずTez使っとけ的な感じで僕は使っています。簡単なオプションでMapreduceからTezに切り替えたりできます。

## クエリエンジン
MapReduceの計算結果を取り出すにはJavaによるプログラミングが必要です。
ただ、データベースからデータを取り出す時にはSQLみたいに簡単にデータの取り出したいですよね。
そのような思いからMapReduceの演算結果をSQL"風"に取り出せるように開発されたのがHiveです。

### Hive
sql風に記述されたhqlを書くことで、SQLっぽくデータを取り出すことができます。
普通にSELECT文とかが使えます。
ただし、内部で行われている演算はSQLとは別物なので、効率良くhqlを書くためにはある程度どのような計算が内部で行われているか知っていた方が良かったりします。
例えばWHERE句で程度データを絞る前にJOINを行なったりすると、JOINの対象となるデータが大きくてめちゃくちゃ時間がかかったりします。
また、分散処理を行う際に特定のノードに負荷がかかりすぎたりすると、そこがボトルネックとなって計算が遅くなったりします。
などなど完全にSQLと同じではないのですが、多くのエンジニアはSQLに慣れ親しんでいるためJavaを使うのに比べるとHiveを使った方が圧倒的に便利ですよね。
ちなみにHiveのマスコットキャラはこんな感じです。Hadoop上を自由に飛び回る蜂をイメージしてるのだと思われますが、僕は初めてみたとき怖くて泣きそうになりました。

<img width="160" alt="![スクリーンショット 2020-06-21 17.26.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547532/f55789d6-0c85-f44d-ac82-6737d5ed52ee.png">


- **ORC**

高速で計算するためにMapReduceを始めとした並列化をすることはとても重要ですが、データの保存形式も同じくらい重要です。
Hiveでデータを集計しテーブルに格納する際にはORCと呼ばれる列指向のストレージ形式で保存することができます。
これは簡単に言えば行ではなく列（カラム）ごとにまとめてデータを保存するということです。
Hiveでの集計を行う際に、「特定のカラムを取り出して平均や合計を求める」といった処理をよく行います。
この時に列ごとに保存されていた場合、全ての行から対象のカラムのデータを読み出さなければいけないため時間がかかります。
このようにORCの形式はデータの読み出し面では高速ですが、通常の列ごとに保存する方法と比べてデータの書き出しに時間がかかります。
なので万能というわけではありませんが、いったん作ったテーブルから頻繁に集計を行う際にはORCで保存しておく方が便利ですね。

### Presto
以上のようにHiveは非常に便利ですが、万能ではありません。
弱点としては大容量のデータをバッチ処理したりするのには向いてますが、テーブルの中身をちょっと確認するようなアドホックな処理には向いていません。いちいちYARNを介してHDFSから読みだしたデータをMapとReduceを通して中間データをディスクに書き出して...といった処理が入るからです。
PrestoはFacebookで開発された対話型に特化したクエリエンジンです。
PrestoではYARNのようなリソースマネージャを使わず、中間データもディスクに書き出さず全てメモリ上で処理します。
そのため内容によってはかなりメモリを消費し大容量のバッチ処理には向きませんが、そうでなければHiveに比べて非常に高速です。
HiveとPrestoはどちが優れているといったものではないので用途によって使い分けるのが良いと思います。
どちらも似たような文法でかけますが、完全に同一ではないため微妙に書き方が違う箇所もあります。


## Sparkとは
他にもいろいろあるのですが、最後にSpark （Apache Spark）を紹介して終わります。
SparkでググるとHadoop v.s. Sparkみたいな文脈でいっぱい出てきますが、最初の図にちょろっと書いてあるようにHDFSやYARNの上に載せることもできます。
SparkではPrestoのように中間データをディスクではなくメモリ上で処理することで高速化を実現しています。
詳しい説明はしませんが、RDD(Resilient Distributed Datasets)という仕組みを使うことでいい感じにメモリ上で並列化を実現しています。

SparkはHiveやPrestoのようにクエリエンジンとして使うことができますが、その強みはむしろ一連の処理をPythonやScalaといった言語で記述できるところにあります。
例えば大容量のデータを読み込んで機械学習を行なったりといったこともできます。

<img width="250" alt="![スクリーンショット 2020-06-21 17.28.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547532/b531b2c6-e3b1-9e45-8ce4-dd96674f6250.png">


## まとめ
 - Hadoop周りの用語をざっくりまとめました
 - 間違いなどがあれば随時修正、追記します