Apache Arrowフォーマットはどのようにクエリー結果の転送を高速にしているのか
Published
10 Jan 2025
By
Ian Cook, David Li, Matt Topol, Sutou Kouhei [訳]
Translations
原文(English)
この記事はデータベースとクエリーエンジン間のデータ交換フォーマットとしてなぜArrowが使われているのかという謎を解くシリーズの最初の記事です。
「どうしてこんなに時間がかかるの?」
これはデータを扱っている人がクエリー結果を待っている間によく考える質問です。たくさんの回答が考えられます。もしかしたら、データソースが適切にパーティショニングされていないかもしれません。もしかしたら、SaaSのデータウェアハウスのリソースが足りないのかもしれません。もしかしたら、クエリーオプティマイザーがSQL文を効率的な実行計画に落とし込めなかったのかもしれません。
しかし、驚くほど多くの場合、クエリ結果をクライアントに転送するために非効率なプロトコルを使っていることが答えになります。2017年の論文では、Mark RaasveldtとHannes Mühleisenは、特にクエリー結果が大きい場合、クエリー結果の転送がクエリー実行時間の大部分を占めることがよくあることを観測しました。しかし、ボトルネックはあなたが予想している場所ではありません。
送信元から受信先へのクエリー結果の転送は次の3つのステップになります。
- 送信元:結果を元のフォーマットから転送用のフォーマットにシリアライズ
- 送信元:転送用のフォーマットでネットワーク経由でデータを送信1
- 受信先:転送用のフォーマットのデータを扱いやすいフォーマットにデシリアライズ
ネットワークが遅かった時代は、通常はデータ転送ステップ(ステップ2)がボトルネックでした。そのため、シリアライズステップ(ステップ1)とデシリアライズステップ(ステップ3)を高速にする動機はほとんどありませんでした。その代わり、転送するデータを小さくすることに重点がおかれていました。多くの場合は転送時間を短縮するためにデータを圧縮していました。広く使われているデータベース接続API(ODBCとJDBC)とデータベースクライアントプロトコル(MySQLのクライアント・サーバープロトコルやPostgreSQLのフロントエンド・バックエンドプロトコル)はこの時代に設計されました。しかし、ネットワークは高速になり、転送時間が短縮されたため、ボトルネックはシリアライズステップとデシリアライズステップに移ってきました2。これは大きな結果を生成するクエリーで特に当てはまります。多くのデータエンジニアリングパイプライン・データ分析パイプラインではこのようなクエリーがよく実行されます。
今でも多くのクエリー結果はレガシーなAPI・プロトコルで転送されています。これらのAPI・プロトコルでは非効率な転送用のフォーマットを使わないといけないので、多くのシリアライズ・デシリアライズオーバーヘッドがあります。2021年の論文では、Tianyu LiらはODBCとPostgreSQLプロトコルを使う例を示しました。この例では、総クエリー実行時間の99.996%がシリアライズ・デシリアライズに費やされていました。これは極端なケースですが、90%以上費やされている実例をたくさん見てきました。今では、データエンジニアリングクエリー・データ分析クエリーのために、シリアライズ・デシリアライズを高速にする転送用フォーマットを選択する強い動機があります。
そこでArrowですよ!
Apache Arrowオープンソースプロジェクトはデータフォーマットを定義しています。このフォーマットはクエリー結果転送時のシリアライズ・デシリアライズを高速にするために設計されています。多くの場合は、シリアライズ・デシリアライズは不要になります。2016年に作られて以来、Arrowフォーマットおよびこのフォーマットを中心に構築された多言語対応ツールボックスは広く使われるようになりました。しかし、Arrowがどのようにシリアライズ・デシリアライズのオーバーヘッドを削減しているかの技術的な詳細はあまり理解されていません。この問題を解決するために、シリアライズ・デシリアライズのオーバーヘッドを削減することを可能にするArrowフォーマットの5つの特徴を説明します。
1. Arrowフォーマットは列指向
列指向(カラムナー)データフォーマットは各カラムの値をメモリー上の連続した領域に保持します。これは行指向データフォーマットとは対象的です。行指向データフォーマットは各行の値をメモリー上の連続した領域に保持します。

高性能な分析データベース・データウェアハウス・クエリーエンジン・ストレージシステムは列指向アーキテクチャーを採用することが多いです。これは、よく使われる分析クエリーを高速に実行するためです。最新の列指向クエリーシステムは、Amazon Redshift・Apache DataFusion・ClickHouse・Databricks Photon Engine・DuckDB・Google BigQuery・Microsoft Azure Synapse Analytics・OpenText Analytics Database (Vertica)・Snowflake・Voltron Data Theseusなどです。
同様に、分析用クエリー結果の多くの出力先も列指向アーキテクチャーを採用しています。出力先は、たとえば、BIツール・データアプリケーションプラットフォーム・データフレームライブラリー・機械学習プラットフォームなどです。列指向のBIツールは、Amazon QuickSight・Domo・GoodData・Power BI・Qlik Sense・Spotfire・Tableauなどです。列指向のデータフレームライブラリーは、cuDF・pandas・Polarsなどです。
そのため、クエリー結果の送信元のフォーマットと受信先のフォーマットがどちらも列指向フォーマットであることがますます一般的になっています。列指向の送信元と列指向の受信先でもっとも効率的にデータを転送する方法は列指向の転送用フォーマットを使うことです。これにより、行と列を転置するという時間のかかる処理をせずに済みます。行指向の転送用フォーマットを使うと、データ転送元のシリアライズ処理で列を行に転置し、データ受信先のデシリアライズ処理で行を列に転置しないといけません。
Arrowは列指向のデータフォーマットです。Arrowフォーマットのデータの列指向のレイアウトは、広く使われている送信元システム・受信先システムでのデータのレイアウトと似ています。多くのケースでは似ているのではなく同一のレイアウトになっています。
2. Arrowフォーマットは自己記述的で型安全
自己記述的なデータフォーマットではスキーマ(カラムの名前と型)とスキーマ以外のメタデータ(データの構造を説明するメタデータ)は、データの中に入っています。自己記述的なフォーマットはデータを安全かつ効率的に処理するために必要なすべての情報を受信したシステムに提供します。一方、自己記述的ではないフォーマットでは、受信したシステムはスキーマや構造を推測する(これは遅くエラーが発生しやすい処理)か、別途スキーマを取得しなければいけません。
いくつかの自己記述的なデータフォーマットの重要な特徴は型安全を強制することです。フォーマットが型安全を強制する場合、データの値は指定された型に準拠していることが保証されるため、受信したシステムはデータを処理するときに型エラーが発生する可能性を排除できます。一方、型安全を強制しないフォーマットでは、受信したシステムはデータ内の各値の有効性をチェックする(これは計算コストが高い処理)か、データを処理するときに型エラーを処理する必要があります。
自己記述的でなく型安全でもないCSVのようなデータを読むとき、データのスキャン・推測・チェックのすべての処理がデシリアライズの大きなオーバーヘッドになります。さらに悪いことに、このようなフォーマットはあいまいさ・デバッグの問題・メンテナンスの課題・セキュリティの脆弱性につながる可能性があります。
Arrowフォーマットは自己記述的で型安全を強制します。さらに、Arrowの型システムは広く使われているデータ送信元・受信先と似ています。多くのケースでは同じかそれらのスーパーセット(それらよりも表現力が高い)になっています。ここでのデータ送信元・データ受信先には、ほぼすべての列指向データシステムと多くの行指向データシステムが含まれています。たとえば、Apache Sparkやリレーショナル・データベースなどが含まれています。Arrowフォーマットを使うと、これらのシステムはネイティブな型と対応するArrowの型の間ですばやく安全にデータの値を変換できます。
3. Arrowフォーマットはゼロコピー可能
ゼロコピー操作とは、中間コピーをまったく作成せずにあるメディアから別のメディアにデータを転送する操作です。データフォーマットがゼロコピー操作をサポートしている場合、メモリー上の構造はディスク上あるいはネットワーク上の構造と同じになります。そのため、たとえば、メモリー上で使える構造のデータをネットワークから直接読み込めます。このとき、中間コピーや変換をする必要はありません。
Arrowフォーマットはゼロコピー操作をサポートしています。データの値の集まりを保持するために、Arrowはレコードバッチと呼んでいる列指向の表形式のデータ構造を定義しています。Arrowのレコードバッチはメモリー上に保持することもできますし、ネットワーク経由で送信することもできますし、ディスクに保存することもできます。レコードバッチがどのメディアにあってもどのシステムで生成されてもバイナリー構造は変わりません。スキーマと他のメタデータを保存するために、ArrowはFlatBuffersを使っています。FlatBuffersはGoogleが作ったフォーマットです。FlatBuffersも、どのメディア上でも同じバイナリー構造になります。
これらの設計判断により、Arrowは転送用のフォーマットとしてだけでなく、メモリー上のフォーマットとしてもディスク上のフォーマットとしても使えます。これは、JSONやCSVといったテキストベースのフォーマットやProtocol BuffersやThriftといったシリアライズされたバイナリーフォーマットとは対照的です。これらのフォーマットは専用の構文を使ってデータをエンコードします。これらのフォーマットのデータをメモリー上で使える構造にロードするには、データをパースしてデコードする必要があります。これはParquetやORCといったバイナリーフォーマットとも対照的です。これらはディスク上でのデータサイズを削減するためにエンコードしたり圧縮したりします。これらのフォーマットのデータをメモリー上で使える構造にロードするためには、展開してデコードする必要があります3。
データ送信元のシステムでは、メモリー上あるいはディスク上にArrowフォーマットのデータがあればシリアライズせずにArrowフォーマットでネットワーク越しにデータ転送できるということです。また、データ受信先のシステムでは、デシリアライズせずにネットワークからメモリー上にデータを読み込んだりディスク上にArrowファイルとして書き出したりできるということです。
Arrowフォーマットは非常に効率よく分析操作できるメモリー上のフォーマットとして設計されています。このため、多くの列指向データシステムは内部のメモリー上のフォーマットとしてArrowを採用しています。たとえば、Apache DataFusion・cuDF・Dremio・InfluxDB・Polars・Velox・Voltron Data Theseusなどが採用しています。これらのシステムがデータ送信元あるいはデータ受信先である場合、シリアライズ・デシリアライズのオーバーヘッドは完全になくなります。他の多くの列指向のデータシステムの場合、それらが使っているプロプライエタリなメモリー上のフォーマットはArrowと非常に似ています。それらのシステムでは、Arrowフォーマットとのシリアライズ・デシリアライズ処理は高速で効率的です。
4. Arrowフォーマットはストリーム可能
ストリーム可能なデータフォーマットはデータセット全体を待たずに1つのチャンクずつ順番に処理できます。データがストリーム可能なフォーマットで転送されているとき、受信先のシステムは最初のチャンクが到着したらすぐに処理を開始できます。これによりいくつかの方法でデータ転送を高速化できます。たとえば、データを処理している間に次のデータを受信できます。たとえば、受信先のシステムはメモリーをより効率的に使うことができます。たとえば、複数のストリームを並列に転送することができます。これにより、データ転送・データのデシリアライズ・データ処理を高速化できます。
たとえば、CSVはストリーム可能なデータフォーマットです。なぜなら、(もし含まれているなら)ファイルの先頭のヘッダーにカラム名があって、ファイル中のそれ以降の行は順番に処理できるからです。一方、ParquetとORCはストリーム可能ではないデータフォーマットです。なぜなら、データを処理するために必要なスキーマと他のメタデータがファイルの最後のフッターにあるからです。処理を始める前にファイル全体をダウンロードする(あるいはファイルの最後まで移動してフッターを別途ダウンロードする)必要があります4。
Arrowはストリーム可能なデータフォーマットです。データセットは同じスキーマを持つレコードバッチの列としてArrowで表現できます。Arrowはストリーミングフォーマットを定義しています。このフォーマットでは、まずスキーマがあり、そのあと、1つ以上のレコードバッチがあります。Arrowストリームを受信するシステムは受信した順にレコードバッチを処理できます。

5. Arrowフォーマットは汎用的
Arrowは表形式のデータをメモリー上で扱うためのデファクトスタンダードなフォーマットとして登場しました。Arrowは言語に依存しないオープンな標準です。様々な言語向けにArrowデータを扱うためのライブラリーが用意されています。たとえば、C・C++・C#・Go・Java・JavaScript・Julia・MATLAB・Python・R・Ruby・Rust・Swift用の公式ライブラリーがあります。主流の言語で開発されているアプリケーションはArrowフォーマットでデータを送受信する機能をサポートできます。JDBCなどのいくつかデータベース接続APIでは特定の言語のランタイムを使わないといけませんが、Arrowフォーマットではそのような必要はありません。
Arrowの汎用性により、実際のデータシステムを高速化する際の基本的な問題に対処できます。その問題とは、性能向上はシステムのボトルネックに律速するということです。この問題はAmdahlの法則として知られています。実際のデータパイプラインでは、クエリー結果が複数のステージを流れることはよくあり、各ステージでシリアライズ・デシリアライズのオーバーヘッドがあります。たとえば、もし、あなたのデータパイプラインに5つのステージがあり、そのうちの4つのステージでシリアライズ・デシリアライズオーバーヘッドを取り除くことができたとしても、あなたのシステムは速くならないでしょう。なぜなら、残った1ステージのシリアライズ・デシリアライズがパイプライン全体のボトルネックになるからです。
Arrowはどんな技術スタック上でも効率的に動くので、この問題の解決に役立ちます。たとえば、こんなデータフローがあったとしたらどうでしょう。NVIDIAのGPUを積んだワーカーを持つScalaベースの分散バックエンド→JettyベースのHTTPサーバー→Pyodideベースのブラウザーフロントエンドを持つNode.jsベースの機械学習フレームワークを使ってユーザーとやりとりするRailsベースの特徴量エンジニアリングアプリ。問題ありません。Arrowライブラリーはこれらのすべてのコンポーネント間のシリアライズ・デシリアライズオーバーヘッドを取り除けます。
まとめ
より多くの商用・オープンソースのツールがArrowに対応するにつれ、シリアライズ・デシリアライズのないあるいは少ない高速なクエリー転送がますます一般的になっています。現在では、多くのデータベース・データプラットフォーム・クエリーエンジンがArrowフォーマットでクエリー結果を転送できます。たとえば、Databricks・Dremio・Google BigQuery・InfluxDB・Snowflake・Voltron Data Theseusといった商用プロダクトや、Apache DataFusion・Apache Doris・Apache Spark・ClickHouse・DuckDBといったオープンソースプロダクトがサポートしています。これにより大幅に高速化しています。
- Apache Doris: 「20倍から数百倍」高速化
- Google BigQuery: 最大「31倍高速化」
- Dremio: 「10倍以上高速化」
- DuckDB: 「38倍」高速化
- Snowflake: 「最大10倍」高速化
データ受信側では、データを扱っている人はArrowベースのツール・ライブラリー・インターフェイス・プロトコルを使うことでこの高速化を最大化できます。2025年には、より多くのプロジェクトとベンダーがADBC標準をサポートして、Arrowフォーマットでクエリー結果を受け取ることができるツールの数が増大するでしょう。
このシリーズの今後の記事を楽しみにしていてください。Arrowフォーマットと他のデータフォーマットを比較して、Arrowフォーマットで結果を取得するためにクライアントが使うことのできるプロトコルとAPIを説明します。
-
転送用のフォーマットは「ワイヤーフォーマット」や「シリアライズフォーマット」と呼ばれることもあります。 ↩
-
1990年代から現在に至るまで、ネットワーク性能の向上はCPU性能の向上を上回っています。たとえば、1990年代後半は、主流のデスクトップCPUはおおよそ1GFLOPSで処理でき、一般的なWANの接続速度は56Kb/sでした。現在、主流のデスクトップCPUはおおよそ100GFLOPSで処理でき、一般的なWANの接続速度は1Gb/sです。つまり、CPUの性能はおよそ100倍向上していて、ネットワーク速度はおよそ1万倍向上しています。 ↩
-
これはアーカイブ用のストレージのようなアプリケーションにおいてもParquetやORCよりArrowの方が速いということではありません。このシリーズの今後の記事では、ArrowフォーマットとParquet・ORC・それ以外のフォーマットをより技術的な詳細に踏み込んで比較します。そして、これらが相互に補完しあうものであることを説明します。 ↩
-
これはCSVがParquet・ORCよりも高速に結果を転送できるということではありません。CSVとParquet・ORCの転送性能を比べるときは、通常、この特徴よりもここで説明している他の4つの特徴の影響の方が大きいです。 ↩