ハクソク

世界を動かす技術を、日本語で。

コマンドラインツールはあなたのHadoopクラスターより235倍速い可能性がある (2014)

概要

  • Hadoopなどの分散処理ツールは、単純なデータ分析にはオーバースペックとなる場合が多い。
  • コマンドラインツールを活用することで、圧倒的な処理速度の向上が可能。
  • 並列処理ストリーム処理を駆使すれば、少ないメモリで大量データを高速処理。
  • 実例として、チェスゲームデータの集計で235倍以上の速度向上を実現。
  • 適材適所でシンプルなツール選択の重要性を解説。

コマンドラインツールはHadoopクラスタより235倍高速

  • Amazon EMRmrjobを使ったチェスゲーム統計分析事例の紹介。
  • 分析対象データは約1.75GB、約200万件のチェスゲーム記録。
  • Hadoopクラスタ(7台構成)での処理は約26分(1.14MB/sec)。
  • ローカルPC+シェルコマンドでの処理は約12秒(270MB/sec)。
  • Hadoopは学習や実験には有効だが、単純集計には過剰な選択となるケース。

シェルコマンドによる並列ストリーム処理

  • catgrepawkなど基本的なシェルコマンドのパイプライン構築。
    • 例: cat *.pgn | grep "Result" | sort | uniq -c
  • メモリ使用量は極小で、ストリーム処理により全データをRAMに載せる必要なし。
  • sort | uniqの代替としてAWKを活用し、さらなる高速化を実現。
    • 例: cat *.pgn | grep "Result" | awk '{...}'
  • grepのCPUボトルネックをxargsによる並列化で解消。
    • 例: find . -type f -name '*.pgn' -print0 | xargs -0 -n1 -P4 grep -F "Result" | ...
  • AWKによるフィルタ処理+集計で、さらなるパフォーマンス向上。
    • 例: find ... | xargs ... awk '/Result/ {...}' | awk '{...}'

パイプライン最適化と最終的な速度向上

  • mawk(高速なAWK実装)の利用で処理速度をさらに向上。
    • 例: find ... | xargs ... mawk ... | mawk ...
  • 最終的に約12秒で3.46GBのデータ処理(約270MB/sec)。
  • Hadoop比で約235倍の速度を達成。

適材適所のツール選択の重要性

  • Big Dataツールは大規模分散処理が本当に必要な場合のみ有効。
  • 多くの分析タスクはシェルコマンドRDBMSで十分対応可能。
  • 実装コスト保守性を考慮し、最適なツール選択を推奨。
  • シンプルなツールの活用がパフォーマンスと効率向上に直結。

まとめ

  • 単純な集計やストリーム処理にはコマンドラインツールが圧倒的に有利。
  • 並列化ストリーム処理を駆使することで、分散環境を凌駕するパフォーマンス。
  • ツール選択は処理内容・データ量・運用負荷に応じて柔軟に。

Hackerたちの意見

以前に投稿された時のセレクション: (2018年, 222コメント) https://news.ycombinator.com/item?id=17135841 (2022年, 166コメント) https://news.ycombinator.com/item?id=30595026 (2024年, 139コメント) https://news.ycombinator.com/item?id=39136472 - この投稿と同じ投稿者によるものです。
データエンジニアとして働いていた時、ギガバイトのJSONを毎秒10MBで処理していたBashとPythonのスクリプトをC#に書き直したんだ。これが大きなボトルネックになってた。ストリーミングパースみたいなちょっとした最適化を適用することで、ほぼディスク速度(当時のSSDで1GB/s)で動かせるようになった。こういうクラスタリングアプローチが本当に意味を持つのは、どれくらいのデータが必要なんだろう?
> ギガバイトのJSONを処理していたBashとPythonのスクリプトをC#に書き直したんだ。あはは、めっちゃ面白い!15年前に全く逆のことをやったのを覚えてるよ。初心者の開発者が、JSONを処理するために複数のプロセスを使って全体がつながったシステムを作ってて、すごく時間がかかったんだ。それがBashスクリプトとPythonに置き換わった! > こういうクラスタリングアプローチが本当に意味を持つのは、どれくらいのデータが必要なんだろう?他の人がどのくらいの閾値を使っているのかは正確には分からないけど、効率的に処理するのに1日以上かかるなら、単一のマシンでプログラムを実行するよりも、もっと良い方法を考えた方がいいと思う。
JSONをストリーミングパースするってどうやるの?全体を取り込まないと文法的に正しいか確認できないと思ってたし、ほとんどのパーサーは未完成や無効なJSONでは動かないんじゃない?それとも、そんなに簡単じゃないのかな。
データの量だけじゃなくて、データ上で何を実行しているかも重要だよ。結合やグループ化は、どんな集約よりもずっとスケールしやすい。さらに、大きなチームが全てのデータ処理ジョブのために構造化された方法でコードを共有できる統一プラットフォームがある。これは、企業がk8sを使ってソフトウェア開発の人間側を管理するのと似ているね。ただ、主要なクラウドプロバイダーで顧客のためにSpark Coreを最適化していた時、急速に改善が見られたのは、垂直スケールされたハードウェアを持つマシンを減らすことで、ほぼ常に分散システムよりもパフォーマンスが良かったこと。実際の価値は、リトライを行ったり、未利用のハードウェア(スポットインスタンスやスケールが低い時の自社データセンター)を活用したり、ハードウェアの故障に対処したりする能力から来ることが多い。これら全てのツールが機能する能力があるからこそ。
処理時間の閾値(例えば1日)についてのピアコメントの回答が好きだな。もう一つ明らかな閾値は、ローカルディスクに収まらないデータだね。大規模処理ソリューションは、S3のようなオブジェクトストアから直接処理できることが多い。そして、同じプロバイダー内で動いている場合(例えば、S3のAWSの場合)、データはローカルSSDよりもずっと速くストリーミングできることが多い。10GB/sは10年以上前から利用可能で、最近では100GB/sも利用できると思う。
> こういうクラスタリングアプローチが本当に意味を持ち始めるには、どれくらいのデータが必要なんだろう?あなたのコメントは前に見なかったけど、チェスの話に戻ると、https://news.ycombinator.com/item?id=46667287を見てみて。約14TBの非圧縮データだよ。そんなに巨大じゃないし、ディスクには確実に収まるけど、普通のノートパソコンには無理だね。
以前、PyConでパネルディスカッションをしたときのことを思い出す。たしか、パッケージングの文脈でanacondaの話をしていて、尊敬されているデータサイエンティスト(彼のトークはいつも大人気)が、「Pandasはエクセルじゃないから好きじゃない」と言ってた。彼にとっては、エクセルがほとんどの探索的作業のためのツールだったんだ。データが大きすぎるときはサンプリングしたりしてたけど、結局のところ彼の仕事はエクセルでやってた。データをクリーンアップするためにちょっとしたPythonやbashを使うのもいいと思うし、LLMのおかげで簡単にサクッとスクリプトを書くことができるようになったよね。
アダム・ドレイクの例(OP)もディスクからストリーミングしてるよ。そして、Unixパイプラインはタスク並列だね。
> こういうクラスターアプローチが本当に意味を持つのは、どれくらいのデータが必要なんだろう? クラスターを正当化するには、ものすごい量のデータ(またはデータ処理)が必要だよ。単一のマシンはかなりスケールアップできる。お金はかかるけど、24x128GB RAM、24x30TB SSDのシステムを注文すれば、数日で届いて3TBのRAM、720TBの(速い)ディスクが手に入る。もっと大きくすることもできるけど、ちょっとエキゾチックになって、注文プロセスが長くなるかもしれない。もしそれ以上のストレージやRAMが必要なら、クラスターが必要だし、単一システムのストレージで得られる処理能力が足りないなら、クラスターが必要になるけど、約256コアのCPUは多くのことには十分だよ。
この記事が2014年のものであることが悲しいのは、状況が悪化していると言えるから。今では、RAMに収まるデータセットにもさらに多くの抽象化レイヤー(Airflow、dbt、Snowflake)が適用されてる。スタートアップが1万ドル/月を分散コンピュートクラスターに使って、10GB未満のログを処理しているのを見たことがある。単に「モダンデータスタック」を設定することが昇進につながるからで、堅牢なBashスクリプトを書くことは「スケーラブルじゃない」とか「ハッキー」と見なされている。効率とはズレたインセンティブだよね。
ある意味では悪化してるけど、別の意味では良くなってる。DuckDBはこういうタスクにとても優れたツールだよ。並列読み込みができるから、コマンドラインツールよりも速いことが多いと思うし、文法も理解しやすいからね。
このパターンは前にも見たことがある。シンプルな代替案に対する反発は、市場投入までの短い時間が必要な需要と供給側の知識不足から来てるみたい。エンジニアが何かを「ハッキー」と呼ぶたびに、彼らは自分の能力の限界に挑んでるんだなって思う。
同意するよ。昇進するためだけじゃなくて、雇われるためにも、一般的に人々が求めるものでもある。初めてのDevOps担当者を探してるなら、DevOpsの経験がある人が欲しいよね。彼らは「Serious Business™」をやるために使った素晴らしいフレームワークやツールについて教えてくれるし、あなたは感心して雇うことになる。そしたら、彼らはその通りに会社のために働いてくれて、未来に向けての準備ができた気分になる。誰も反対しないから、結局は基本的なデスクトップでも十分に対応できる状況になっちゃうんだよね。
RAMに常駐するデータセットには、DuckDBかclickhouse-localがベストな解決策だよ。SQLっぽいデータを使う方が、たくさんのbashスクリプトを書くよりも簡単で、すごくパワフルだからね。
> RAMに完全に収まるデータセット。うん、今はもっと多くのデータセットがRAMに完全に収まるようになってるよ。最近の価格の急騰は置いといて、ノートパソコンで128GBのRAMは全然実現可能だし、可能な限界でもない。2014年には4GBのコンピュータがまだ普通だったから、そんなのは夢のまた夢だったよね。もちろん、サーバーの場合は最大RAMがもっと高いし、多くのシナリオでは高速なローカルSSDからストリーミングするのがほぼ同じくらい良いかもしれない。
私はこの20年間、正しいことをして、履歴書にかっこいい技術じゃなくて意味のある技術を使ってきた。でも、解雇されちゃった。今、履歴書には現代的なフレームワークがほとんどなくて、1年以上無職だよ。今は本当にバカみたいに感じてる。
そうだね。クラウドプロバイダーは常にお金をもらうし、開発者や管理者が電源を切り忘れると、日曜日に二重にお金をもらうことになる。いつもと同じ話だよ、昔はオラクル認定技術だったけど、今はアマゾンにお金を払わせるためのAWS技術が認定されてる。
逆に、ブログ記事の重要なメッセージは、必要でない限り全データセットをRAMに読み込むなってことだよ。パターンが合うときはストリーミングするのがコツ。これが、私たちの分野が100GBを超えるファイルを扱うときのやり方だよ。
最近、スケーリングの問題が一台のマシンで楽に収まるようなインタビューをいくつか受けたんだけど、一番面白かったのは、1日あたり1GBのJSONを取り込むってやつだった。基本からどうやって収まるか説明したら、「エンジニアたちはあなたの技術的な評価には同意したけど、求めていた答えじゃないから、今回は見送ることにする」とフィードバックが来た。こういう経験は何度もあるんだよね。多くの人が、今のマシンはTB単位のRAMや何百もの物理コアを持ってるってことに気づいてないと思う。一台のマシンって、今はめちゃくちゃデカいんだよ。
この記事に関連するちょっとした歴史を知りたい人のために... 記事に出てくるmrjobは、Hadoopを使わずにローカルコンピュータで動くローカルモードがあるんだ。そのモードは、後でHadoopクラスターでより多くのデータを処理するために開発するジョブ用なんだけど、小さいデータセットの場合、そのローカルモードはHadoopクラスターで動かすよりもかなり速いことがある。特に一時的なAWS EMRクラスターでは、小さいジョブの場合、ローカルモードがクラスターが立ち上がる前に終わることも多い。それでも、著者のアプローチはそのデータセットに対してmrjobのローカルモードよりもかなり速いと思う。MapReduceがもたらしたのは、スケールアップを簡単にする制約のある計算モデルだった。それにはトレードオフがあって、必要ないスケールの場合はあまり価値がないことが多い。ここでのスケールアップは、当時のディスクに簡単に収まらないデータを指していて、S3からのデータのストリーミング入出力がシームレスにできるのは強力だった。2010年代初頭にmrjobをたくさん使っていて、私が関わったジョブは累計で何ペタバイトものデータを処理していた。2010年にリリースされた時、その使いやすさは本当に驚くべきものだった。でも、最近はあまり関係なくなってきてるね。
多くの開発者はWindowsで技術を学んで、こういうツールに触れることがないんだよね。それに、ループやif文よりも高い抽象レベルで動くから、ちょっとした読み込みが必要だし。暗黙のループがあったり、フィールドが自動的に切り分けられたり、すべてのフィールドに同時に正規表現を適用できたりするから、未経験者には分かりにくい。でも、CLIではすごくパワフルで柔軟性があって、急ごしらえのソリューションをすぐに作れるから、仕事をこなすことができるし、少なくとも大きな武器を使う前の基準にはなるよ。
その通り!最近、マネージャーや若手エンジニアに対して、スパークや分散ツールがデータエンジニアリングの正しい方法だと説得する業界の動きがすごく強いと思う。ウェブ開発のインフルエンサーが、静的サイトで十分なのに巨大なハイドレーテッドSPAフレームワークを作らせるようなパターンに似てる。私のアドバイスは、この混乱から抜け出すために: - マネージャーの皆さん、特定のソリューション(スパークやリアクト)を求めないで。賢いエンジニアに問題を解決させて、あなたが気にしていること(コストやパフォーマンスなど)を最適化・追跡させてください。彼らを雇ったのは、彼らが最善を知っているからで、たぶん本当に知ってるよ。 - テクニカルリードの皆さん、マネージャーが「ハイパースケールはどうするの?」って言ってきたら、「既存のソリューションは永遠にスケールする」って言わなくてもいいよ。「うちのパイプラインは20GBまでのデータセットを扱えるし、今のところそれ以上は見込んでない。もしそうなったら、x/y/zをやって対応するよ」って言っても大丈夫。マネージャーは、スケールが全てをクラッシュさせるわけじゃないって知りたいだけで、エクセルの処理パイプラインのために全てを最適化したかどうかは気にしてないと思う。
まったくその通り。数年前に(まあまあ有名なユニコーン企業)でデータエンジニアリングチームにいたとき、マネージャーが「次の四半期にスパークを使いたい、これは大きなイニシアティブだ」と言ったんだ。私はすぐに「どんな形で?」って聞いたら、答えは「わからない/関係ない、使ってるって言えればそれでいい」だった。どこからその話が来ているのか、本当に理解できればよかったな(彼のマネージャーが履歴書を盛るため?誰かがキックバックをもらってる?)
でも、ほとんどの企業は小さなデータを扱ってるってことを忘れがちだよね。データセットのサイズの分布はパワー法則に従っていて、ペタバイトサイズのデータセットを扱うエンジニアは少数派なんだ。それでも、求人市場はその経験を履歴書に載せることを奨励していて、給与を上げたいならそうしなきゃいけない。これが過剰なエンジニアリングを促してるんだ。
データと問題がよく理解されているとき、シンプルなアプローチが最適だってことを見落としがちだよね。大きくて高価なツールは、自らが問題になって、さらに管理するためのツールが必要になることもある。(もしかしたらそれが狙い?)問題は、チームや企業が必要以上に早く最適化フレームワークを採用しちゃうこと。シンプルなツールから始めることで、大半の問題は解決できるし、実際にはそれだけで十分なことが多い。
SqliteとPostgresも同じことが言えるよね。ほとんどのスタートアップはPostgresじゃなくてSqliteが必要なんだ。多くのクエリが桁違いに速く動くし、ユーザーにとってもいいし、テストスイートが数分かかるところを数秒で終わるのを見ると、人生が変わった気がする。
データの大きさは、何をするかによって常に変わる。例えば、医療手術のデータを考えてみて:日付、医師名、手術名、成功率。「最も一般的な手術トップ10は?」 - bashで簡単。「その手術の過去1年でのトップ医師(成功率)は誰?」 - これもbashで簡単。「医師の経験が最も影響を与える手術はどれ?」 - これはbashでは非常に難しい。各手術について、その医師がその日に何回その手術を行ったかを計算して、経験の少ない結果と多い結果を比較する必要がある。研究者は、ますます複雑な質問の滑らかな連続体を見るかもしれないけど、計算の複雑さには大きなジャンプがある。50GBのデータセットは、難しい質問をするなら2TBのものより「大きい」かもしれない。ビジネスとしては「データ処理にはSparkを使ってます」って言う方が、「ケースバイケースで特注の処理エンジンを作ってます」って言うより簡単なんだよね。
著者です!何年も前に書いたこの投稿が、今でも人々に役立っているのを見るのは嬉しいね。ここにいる多くの人と同じように、状況は多くの面で悪化していると思う。でも、似たような観点から、マイクロサービスのカゴ・カルトからの脱却が進んでいるのを見て嬉しいよ(このサイトの別の投稿でも触れた話)。企業やチームのパフォーマンス向上を手助けしている皆さん、頑張って!希望はあるよ!