ククログ

株式会社クリアコード > ククログ > Apache Arrowの最新情報(2022年5月版)

Apache Arrowの最新情報(2022年5月版)

Apache ArrowPMC chair(プロジェクトリーダーみたいな感じ)の須藤です。2022年5月時点のApache Arrowの最新情報を日本語で紹介します。

2018年から毎年Apache Arrowの最新情報を日本語で紹介しているのですが、これはその2022年版です。2021年も紹介しようと思っていたのですが、気づいたら2021年が終わっていました。。。ということで、2021年と2022年の新情報を紹介します。2020年以前の情報は過去の紹介を参照してください。

私は、PMCの中では唯一の日本人で、コミット数は3番目に多い1ので、日本ではApache Arrowのことをだいぶ知っている方なはずです。だいぶ知っている人が紹介しているので、これまでの紹介も含めて日本語で読めるApache Apacheの情報として有用なはずです。

ちなみに、英語ではいろいろ情報があります。有用な情報源はApache Arrowの公式ブログ公式メーリングリストやそれぞれの開発者のブログ・発表などです。開発者のブログの中ではVoltron Dataさんのブログがオススメです。直近のイベントだと6月23日に開催されるVoltron Dataさん主催のThe Data Threadがよさそうです。私も(日本語で)なにか話すかもしれません。バーチャルカンファレンスなので日本からでも参加できます。が、日本時間で深夜1:00-3:00開催なので参加しにくいとは思います。なお、Voltron DataさんはApache Arrowを軸にしたスタートアップです。フルタイムでApache Arrowの開発をしている人を何人も雇っていてApache Arrowの開発を強力に推進している企業の1つです。実は、2022年4月から私のApache Arrowの開発時間もVoltron Dataさんが資金援助してくれています。

この記事では英語の情報へのリンクも示しながら最新情報を紹介するので、ぜひ英語の情報も活用してください。

Apache Arrowが実現すること

Apache Arrowが実現することはプロジェクト開始当初から変わっていないので、Apache Arrowの必要性から知りたいという方はApache Arrowの最新情報(2018年9月版)を参照してください。まとめると次の通りです。

Apache Arrowは効率的に大量のデータをメモリー上で処理することを目指しています。そのためにしていることは次の通りです。

  1. 高速データ交換・高速処理しやすいApache Arrowフォーマットの仕様を定義
  2. 各種言語用のApache Arrowフォーマットを読み書きするライブラリーを開発
  3. 大量のメモリー上のデータを高速処理するためライブラリーを開発
  4. 大量のデータを効率よく交換するためのフレームワークを開発

Apache Arrowが向いている用途は次の通りです。

  • 大量データの交換
  • メモリー上での大量データの分析処理

Apache Arrowの現状

それでは、2022年5月現在のApache Arrowについて紹介します。

2020年7月24日にApache Arrow 1.0.0がリリースされたのですが、約2年後である今の最新バージョンはApache Arrow 8.0.0です。すごく上がっていますね!これはApache Arrowのバージョン付け・リリースのポリシーが次のようになっているからです。

  1. セマンティックバージョニングに従う
  2. 3-4ヶ月ごとにメジャーバージョンアップをする(当分の間は開発速度が速く、ほぼ必ずAPI非互換な変更が必要になるだろうから)

バージョン付けとリリースに関してさらに知りたい人はApache Arrowの最新情報(2020年7月版)も参照してください。

この2年で7回リリースしたので8.0.0になったということです。

それではこの7回のリリースでどのような変更があったかを次の観点ごとにまとめて紹介します。

  • 仕様・仕組み
  • 各プログラミング言語

「仕様・仕組み」はデータフォーマットやApache Arrow Flightモジュールといったことで、「各プログラミング言語」とはC++実装やRust実装といったことです。

各プログラミング言語ごとにどの機能が実装済みでどの機能が未実装なのかを示す表が公式ドキュメント内に用意されています。そちらも合わせて参照してください。

データフォーマット

データフォーマットもライブラリーのバージョンと同じようにセマンティックバージョニングに従っています。データフォーマットもApache Arrow 1.0.0のリリースと1.0.0になりましたが、まだ1.0.0のままです。ただ、いくつか互換性のある変更があります。内部的には1.1とか1.2に上がったようになっていますが、リリースはされていません。(フォーマットの公式ドキュメントにバージョン情報を入れるとかして更新したほうがいいな。。。)

  • 256ビットのdecimal(浮動小数点と違って誤差なく小数を表現できる数値型)のサポート
  • カレンダー上の区間(3ヶ月とか)のサポート
    • 単位:
      • 月(3ヶ月とか)
      • 日+ミリ秒(2日と8000ミリ秒とか)
      • 月+日+ナノ秒(3ヶ月と2日と8000ナノ秒とか)

データフォーマットにはストリーミングフォーマットファイルフォーマットがあるのですが、それらのフォーマットの拡張子・メディアタイプ(MIMEタイプ)が正式に決まりました。それぞれ次のようになります。

  • ストリーミングフォーマット:
    • 拡張子:.arrows
    • メディアタイプ:application/vnd.apache.arrow.stream
  • ファイルフォーマット:
    • 拡張子:.arrow
    • メディアタイプ:application/vnd.apache.arrow.file

もろもろの手続きをしたのは私で.arrowsという拡張子を提案したのも私なので感慨深いです。詳細はApache Arrowデータのメディアタイプ(MIMEタイプ)を参照してください。

Apache Arrow Flight

Apache Arrow FlightはApache Arrowデータを効率よくやりとりするためのRPCフレームワークです。

参考情報:

1.0.0リリース当時はApache Arrow Flightに対応しているのはC++実装とJava実装だけでしたが、C#実装やC GLib実装など他の実装でも対応するようになりました。具体的にどの実装が対応したかは後述の各実装のセクションを参照してください。

Apache Arrow Flight上でSQLを使うためのApache Arrow Flight SQLが入りました。Apache Arrow Flight SQLはSQLベースのデータベースと高速にやり取りするための仕組みです。既存のSQLベースのデータベースはそれぞれ独自のプロトコルを使っていますが、データ転送の効率がよくありません。Apache Arrow Flightベースにすることで高速にデータ転送できるようにしようということです。

ただ、既存のSQLベースのデータベースはApache Arrow Flightベースではないので現時点ではApache Arrow Flight SQLで既存のSQLベースのデータベースに接続することはできません。サンプルとしてSQLite3をApache Arrow Flight SQLに対応させたものなどがいくつかあるくらいです。今後、Apache Arrow Flight SQLに対応したSQLベースのデータベースが増えてくるはずです。

参考:Introducing Apache Arrow Flight SQL: Accelerating Database Access

Apache Arrow Flight SQLはSQLベースのデータベースが対応しないと使えませんが、もう一つ、SQLベースのデータベースが対応しなくてもデータ転送を高速化するアプローチが検討されています。それがApache Arrow Database Connectivity(ADBC)です。

ADBCは各種既存の独自プロトコルやODBCでデータベースと接続しますが、接続して取得したデータを高速にApache Arrowデータに変換します。データ転送のボトルネックは通信のためのシリアライズ・デシリアライズのことが多いのでそこを高速化できない分Apache Arrow Flight SQLよりも高速化できませんが、それ以外の部分でできる最適化で高速化するアプローチです。たとえば、既存のデータベースでは行ベースで結果を返しますが、Apache Arrowデータは列ベースなのでその変換をしなければいけません。データベースから複数行をまとめて取得して一気に行ベースと列ベースを変換すれば1行ずつ変換するよりも効率がよいです。そんな最適化をもろもろして高速化します。

ADBCは現在検討中の仕組みなので興味がある人は議論に参加してください。

通信方法としてgRPC以外にUCX (Unified Communication X)も使えるようになりました。UCXはハードウェアリソースなども使って高速に通信するための仕組みです。たとえば、RDMA(Remote Direct Memory Access)でOSを介せずに別ホストにデータを転送して高速化します。

まだ改善の余地はありますが、一部のケースではgRPCよりもUCXを使った方が速かったというベンチマーク結果も出ています。より速いデータ転送が必要という人はUCXバックエンドを試してみてください。

参考:Arrow in HPC

Apache Arrow Dataset

Apache Arrow DatasetはApache Arrow Flightとは違って現時点ではC++実装しかありませんが、独立した「仕組み」として紹介します。C++実装のバインディングがあって、PythonやRubyやRやJavaなど他の言語からもC++実装を使うことはできます。現時点ではC++以外に独自に実装している言語はないということです。

Apache Arrow DatasetはApache Arrowフォーマット・Apache Parquetフォーマット・Apache ORCフォーマット・CSVフォーマットなど各種フォーマットを統一的なAPIで読み書きするためのモジュールです。別の言い方をすると、フォーマットの違いを気にせずにデータを読み書きできるということです。

1.0.0の頃は読み込みしかできませんでしたが、書き込みもできるようになっています。また、複数のファイルにパーティションされたデータも読み書きできます。現時点で対応しているパーティションの方法は次の通りです。

  • ディレクトリーパーティショニング
    • パス中の階層ごとにカラムを割り当ててカラムの値ごとに別ディレクトリーにしてパーティションする。
    • 例:1段目のカラムをyear:int16、2段目のカラムをmonth:int8とし、パスが/2009/11/data.arrowだった場合、data.arrowのレコードすべてにyearカラムとmonthカラムができ、それぞれ値を200911にする。
  • Hiveパーティショニング
    • ディレクトリーパーティショニングと似ているがパスのフォーマットが違う。
    • /${カラム1}=${値1}/${カラム2}=${値2}/...というように値だけでなくカラム名もパスに入れる。
  • ファイル名パーティショニング
    • ディレクトリーパーティショニングと似ているがディレクトリーで値を区切るのではなく、ファイル名内に_で区切って値の情報を入れる。
    • 例:1つ目のカラムをyear:int16、2つ目のカラムをmonth:int8とし、ファイル名が2009_11_data.arrowだった場合、このファイルのレコードすべてにyearカラムとmonthカラムができ、それぞれ値を200911にする。
  • 関数パーティショニング
    • ユーザーがどうパーティションするかをプログラムできる。

非同期・並列での処理をできるようになったので性能が向上しています。

Amazon S3に加えてGoogle Cloud Storage上のデータも透過的に(ローカルのファイルと同じAPIで)扱えるようになっています。Azure Blob Storageにも対応させるプルリクエストもあります。これからも対応するオンラインストレージサービスは増えていくはずです。

少し変わったところだとSkyhookというプログラミング可能なストレージもサポートしました。プログラミング可能なストレージとは、データを処理する機能(プログラム)を追加できるストレージのことです。ストレージ上でデータを処理できるとデータ転送量を削減して効率よくデータを取得できます。たとえば、1年分のデータが入ったファイルから1ヶ月分だけのデータを読みたい場合、ストレージ上でデータを絞り込めば1ヶ月分のデータだけ転送すればよいので効率的です。

参考:Skyhook: Bringing Computation to Storage with Apache Arrow

Substrait

Apache Arrowの一部ではないのですがSubstraitも紹介します。

Substraitはプログラミング言語に依存せずにクエリーを表現するための仕様です。Apache Arrowが高速にデータ転送するためのプログラミング言語に依存しないデータフォーマットを定義していることに似ています。ただ、Substraitは仕様なのでSubstraitで表現されたクエリーを実行する機能は提供しません。Substraitで表現されたクエリーは各データ処理エンジンが処理します。たとえば、Apache ArrowのC++実装にある計算(Compute)モジュールもSubstrait対応のデータ処理エンジンです。

他にもクエリーを異なるデータ処理エンジンで交換したり、クエリーを可視化するときの入力に使ったりといったユースケースを想定しています。

Apache Arrowの中だけでもC++実装の計算モジュールやRust実装のDataFusionなど複数のデータ処理エンジンがあるので、Apache Arrowでも言語を超えてそれらのデータ処理エンジンを連携させるときに使います。

C++

C++実装は独自実装です。(他の実装のバインディングではありません。)

計算(Compute)モジュールがかなり改良されました。計算関数がたくさん増えた(本当にたくさん増えました)こともそうですが、マルチカラムでのソートやグループ化機能なども増えています。現在使える計算関数のドキュメントも用意されたのでどんな計算をできるようになっているかはそちらで確認してください。ちなみに、最近、この計算モジュールに名前をつけない?という議論をしています。

依存ライブラリーをvcpkgでインストールできるようになりました。これまでもCondaで依存ライブラリーを揃えることができましたが同じようなことをvcpkgでもできるようになりました。

リトルエンディアン・ビッグエンディアンを変換できるようになりました。これは石崎さんの仕事です。なお、石崎さんはApache ArrowのコミッターだけでなくApache Sparkのコミッターでもあります。

Apache ORCファイルへの書き出しもできるようになりました。読み込みは前からできたのでこれで読み書きできるようになりました。

対応している型が増えました。たとえば、次の型に対応しました。

  • 256ビットのdecimal(浮動小数点と違って誤差なく小数を表現できる数値型)

OpenTelemetryを使ったトレーシングに対応しました。

C#

C#実装は独自実装です。(他の実装のバインディングではありません。)

Apache Arrow Flightに対応しました。

EOLになった.Net Core 2.1のサポートを終了し、.NET Core 3.1以降が必須になりました。

対応している型が増えました。たとえば、次の型に対応しました。

  • 構造体

C GLib

C GLib実装はC++実装のバインディングです。

Apache Arrow Flightに対応しました。

Cデータインターフェイスに対応しました。

引き続きC++実装に追従し続けていますがだんだん取りこぼしが増えてきました。原因は開発リソース不足です。C++実装は何人もフルタイムで開発している人たちがいるのでもりもり改良されていきます。一方、最近C GLib実装を開発しているのは私とSpeeeの岡田さんくらいです。2人ともフルタイムではないので取りこぼしが増えてきました。ただ、前述の通り、私のApache Arrowの開発時間をVoltron Dataさんが資金援助してくれるようになったので今後は取りこぼしが減っていくはずです。

重要そうな機能はできるだけ優先して追従するようにしているので次のような機能はC GLib実装でも使えます。

  • HDFS/Amazon S3/Google Cloud Storage上にあるデータを読み書きする機能
  • Apache Arrowフォーマット/Apache Parquetフォーマット/CSVフォーマットなど各種フォーマットのデータを読み書きする機能
  • Gandivaを使った行フィルター機能

3.0.0まではGNU AutotoolsあるいはMesonでビルドできましたが、4.0.0からはGNU Autotoolsのサポートをやめました。4.0.0以降はMesonを使う必要があります。

Go

Go実装は独自実装です。(他の実装のバインディングではありません。)

Apache Arrow Flightに対応しました。

対応している型が増えました。たとえば、次の型に対応しました。

  • マップ型
  • 拡張型

Cデータインターフェイスに対応しました。

go/arrow/v${VERSION}とタグを用意するようになりました。これでgo get -u github.com/apache/arrow/go/arrow@v${VERSION}というようにバージョンを指定してGo実装を使えるようになりました。

Java

Java実装は独自実装です。(他の実装のバインディングではありません。)

Apache Arrowファイル内のデータをZstandardまたはLZ4で圧縮できるようになりました。(Apache Arrowファイル全体ではなくデータ部分のみが対象。)

対応している型が増えました。たとえば、次の型に対応しました。

  • 256ビットのdecimal(浮動小数点と違って誤差なく小数を表現できる数値型)

Cデータインターフェイスに対応しました。

後述するRust実装のデータ処理エンジンDataFusionのバインディングが実装されました。

Java 17に対応しました。

JavaScript

JavaScript実装は独自実装です。(他の実装のバインディングではありません。)

C++実装にあるような計算(Compute)モジュールがJavaScript実装にもあるのですがこれが削除されました。

APIがシンプルになったとか他にもいろいろ変更があるのですがちょっと説明しづらいので気になる人は公式ドキュメントを参照してください。

Julia

Julia実装は独自実装です。(他の実装のバインディングではありません。)

3.0.0からオフィシャル実装になりました。

オフィシャル実装になったのですが、その後いろいろあって一度オフィシャル実装から抜けています。ただ、2022年5月現在はまたオフィシャル実装になっています。このあたりは私がサポートしたんですよ!

3.0.0の頃はC++実装などと同じタイミングでのリリース(3-4ヶ月ごとにリリース)だったのですが、再度オフィシャル実装になってからはJulia実装独自のタイミングでリリースするようになりました。明確なルールはありませんが、1つ2つ機能追加・バグ修正が入ったらリリースというような感じです。

リリースタイミングだけでなくバージョン付けもC++実装らとは違います。セマンティクスバージョニングなのは変わりませんが、C++実装らのように3-4ヶ月ごとにメジャーバージョンするというようなことはしていません。互換性が壊れる変更が入ったらメジャーバージョンアップ、そうでない場合は変更内容に合わせてマイナーバージョンアップあるいはパッチバージョンアップです。

MATLAB

MATLAB実装はC++実装のバインディングです。

Featherバージョン1(非推奨になっている)を読み書きする機能だけしかないままですがAPIが改良されています。

Python

Python実装はC++実装のバインディングです。

引き続きC++実装に追従し続けています。C++実装でできることはPythonでもできると思っていいです。

最新のPythonにも対応済みです。M1のmacOS用のwheelも用意されています。サポートが切れたPythonはサポートしていないので古いPythonを使い続けている場合はPythonをバージョンアップしてください。関連して、サポートが切れたmanylinux1のwheelのサポートを終了しました。サポートが切れそうなmanylinux2010のwheelのサポートも近いうちに終了する予定です。

後述するRust実装のデータ処理エンジンDataFusionのバインディングが実装されました。

R

R実装はC++実装のバインディングです。

Apache Arrow Flightに対応しました。

dplyr連携がかなり改良されています。たとえば、C++実装の計算関数をdplyrのfilter()の中で使えるようになっています。他にもグループ化してからの集計や、ジョインなどできることがかなり増えています。

DuckDBなどApache Arrowフォーマットをサポートしている他のプロジェクトとの連携を強化しました。

参考:DuckDB quacks Arrow: A zero-copy data integration between Apache Arrow and DuckDB

ALTREPへの対応も進めています。ALTREPサポートを有効にする(デフォルトでは無効)ことでより高速になります。

Ruby

Ruby実装はC GLib実装のバインディングです。C GLib実装にある機能は自動的にRuby実装でも使えるようになっています。

Ruby 3.0で導入されたMemoryView機能に対応しました。MemoryView機能とはゼロコピーで多次元配列データを共有するための仕組みです。MemoryViewに対応したということはApache Arrowデータを他のRubyライブラリーとゼロコピーで共有できるということです。これまでもred-arrow-numo-narrayなどを使うことでゼロコピーで多次元配列データを共有できましたが、そういうことを一般化した仕組みがMemoryViewです。

参考:MemoryView: Ruby 3.0 から導入される数値配列のライブラリ間共有のための仕組み - Speee DEVELOPER BLOG

Rと同様にDuckDBと連携できますが連携機能はRuby実装に含めずred-arrow-duckdbという外部ライブラリーになっています。これは依存ライブラリーを少なくしてDuckDBとの連携が必要ないケースではDuckDBなしでも使えるようにするためです。(R実装もDuckDB関連ライブラリーがインストールされていれば使えるというレベルの依存にはなっています。)

Rust

Rust実装は独自実装です。(他の実装のバインディングではありません。)

https://github.com/apache/arrow/ 内で開発していたのですが、ここから https://github.com/apache/arrow-rs/https://github.com/apache/arrow-datafusion/ に分離して開発することになりました。理由は次の通りです。

参考:A New Development Workflow for Arrow's Rust Implementation | Apache Arrow

安定版のRustでも使えるようになりました。これまでは安定版のRustでは使えなかったのですが、基本機能は安定版のRustでも使えるようになりました。

Apache Arrow Flightに対応しました。

対応している型が増えました。たとえば、次の型に対応しました。

  • マップ型
  • decimal型

SIMD対応などで高速になっています。

Rust実装開発者の1人がRust実装をいい感じに再実装したArrow2という実装もできました。将来的にこの実装に置き換わるとは思いますがいつになるかはわかりません。

Cデータインターフェイスに対応しました。

Rust実装ベースのDataFusionというクエリーエンジンも改良されています。SQLはいろいろ方言がありますが、PostgreSQLのSQL方言を使う方針にしました。ウインドウ関数に対応するなど機能面での改良もありますし、高速化など性能面での改良もあります。

DataFusionの拡張機能を集めたDataFusion-Contrib organizationができました。DataFusion自体はApache Arrowプロジェクトの一部ですがDataFusion-ContribはApache Arrowプロジェクトの一部ではありません。そのため開発スタイルが違います。

参考:Introducing Apache Arrow DataFusion Contrib

DataFusionは1ノード上で動くクエリーエンジンですがDataFusionをベースに実装されているBallistaという分散計算プラットフォームもApache Arrowに寄付されました。

まとめ

2022年5月時点のApache Arrowの最新情報を、2020年7月からの差分という形でまとめました。Apache Arrowの最新情報をまとめはじめた2018年からApache Arrowはデータ処理界隈で重要なコンポーネントになると言っていましたが、1.0.0がリリースされて数年経った現在、本当にそうなったなと思っています。Apache Arrowに対応したプロダクトは増え、Apache Arrowに対応したクラウドサービスも増えています。今後もApache Arrowの重要度は増えていくでしょう。

私が知っていることはまとめたつもりですが、もしかしたらカバーできていない話があるかもしれません。もし、「○○についても知りたい!」という方がいたら@ktouに声をかけてください。この記事に追加します。

Apache Arrowについて講演して欲しいとかApache Arrow関連の開発のお仕事の相談はお問い合わせフォームからご連絡ください。

自分も仕事でApache Arrowの開発をしたい!という人はクリアコードの採用情報Voltron Dataさんの採用情報を読んでください。あなたと一緒にApache Arrowの開発をすることを楽しみにしています!

  1. 去年は2番目でした。