Apache Sparkをご存知でしょうか。
去年くらいからとても流行っている分散処理フレームワークです。
大量のデータを集計・分析することができます。
公式サイトによれば、インメモリで動作する場合、Hadoop MapReduceより100倍早いそうです。
分散処理は、基本的には1台のマシンでは処理しきれない規模の集計や分析が必要となる場合に必要となります。
Sparkは分散処理のフレームワークなわけです。大量のマシンをクラスターとして扱うことに長けています。
そして当たり前ですが分散処理にはどうしてもオーバーヘッドが発生します。
いくらSparkが高速といっても、シングルノードで実現可能な集計処理をSparkで動かせば遅くなります。
では、シングルノードで計算できるようなデータしか持たないシステムではSparkを使うことにメリットはないのかというと、そんなことはありません。
私は実際に分散処理を必要としない規模のデータにSparkを適用しています。そしてとてもSparkに助けられています。
非分散処理(シングルノード)で使うSparkのメリットについて自分なりに思っていることを書き連ねていきたいと思います。
JSONをSQLでテーブルのように扱える
NginxのアクセスログをJSON形式で出力したものを集計したいとします。
Sparkならこんな感じでアクセスログを集計できます。
val accesses = spark.read.json("paht-to/access.log")
accesses.createOrReplaceTempView("accesses")
spark.sql("SELECT request_uri,COUNT(*) AS cnt FROM accesses GROUP BY request_uri ORDER BY cnt LIMIT 10").show()
リクエストが多かったURIのTOP10を表示するプログラムです。
JSONをSQLを使うことで簡単に集計できています。
超便利ですね。
CPUコア数があれば自前のシングルスレッド処理よりはたぶん早い
Sparkを使えば自分でマルチスレッド処理を実装しなくても勝手にマルチスレッドで処理してくれます。
これを考慮すると、自分でシングルスレッドな集計処理を書くのと比べたらむしろSparkの方が速いのではないでしょうか。
Sparkと同系統の分散処理フレームワークで行っていた処理をマルチスレッドのJavaコードとしてスクラッチで書き直したことがあります。
少なくとも10倍以上は早くなることを想定していたけれど、4~5倍程度しか高速化しませんでした。これは2コアでの結果です。
Sparkはそのフレームワークと同等もしくはそれより速いと仮定すると、自分でシングルスレッドの集計処理を書くのとSparkで集計処理するのとでは、4コア以上あればSparkの方が速いことになります。
Parquetを使うことができる
Parquetというカラム指向のデータフォーマットがあります。
JSONよりも読み込みの効率がよく、集計に向いています。
SparkではParquetを直接扱うことができ、簡単にJSONと相互に変換できます。
色々なデータソースを同時に扱える
Sparkが扱えるのはJSONやCSV、テキストなどのファイルだけでなく、MySQLやHBaseなどのデータベースも扱えます。
SQLでJSONとMySQLのテーブルをJOINしたりできるわけです。
大量のデータ同士でJOINさせるのはあまり現実的ではないかもしれませんが、集計結果をレポート用の
データにまとめるような場合にはかなり便利です。
複雑な集計をすばやく実装できる
色々なデータソースを扱えて、SQLで集計できるため、すべて手続き型言語で集計処理を書くより遥かに早く実装できます。
もしマルチスレッドで書こうと思ったらさらに時間がかかるでしょう。
まとめ
これを見てシングルノードでもSparkが便利だと思っていただけたでしょうか。
頑張ってスクラッチで集計処理を書いたところでSparkとくらべてべらぼうに早くなるわけでもなく、上記のメリットがちょっとしたパフォーマンスの劣化で得られるのであればSparkを使った方がよいのではないかというのが、私の考えです。たいしたデータ量ではなくてもSparkは有用です。
少しでもこれでSparkに興味を持ってくれる人が増えれば幸いです。