Delta LakeをJVMやPySparkなしでRustとPythonプロジェクトで使う
Delta Lake形式を小さなサービスやスクリプトで使おうとしたことがある人なら、すぐに厳しい現実に直面します。数ギガバイトのトランザクションログファイルを読み込むだけで、Apache Spark、そしてそれに伴う重量級JVMインフラを引きずらなければならないのです。大規模データプラットフォームではこれは正当化されますが、ローカルアプリケーション、バックグラウンドマイクロサービス、AWS Lambdaサーバーレス関数にとっては、このような解決策は面倒すぎます。
Delta Lakeコミュニティの開発者たちがこのギャップを埋めることを決意しました。彼らはRustでDelta Lakeを操作するためのネイティブライブラリdelta-rsプロジェクトを作成し、Python向けの公式バインディングも提供しました。
なぜ別のデータライブラリなのか
Delta Lake形式は、オープンファイルストレージの主要な課題を解決するため、優れた形式です。Parquetファイルの上にACIDトランザクションログを追加し、変更履歴と以前バージョンへのロールバック機能(タイムトラベル)、そして厳格なスキーマ強制を提供します。
Delta Lakeを取り巻くクラシックなスタックは、歴史的にScalaとJavaに結びついていました。主なスタックがRust、またはPySparkのような重いフレームワークを使わない軽量なPythonの場合、delta-rsが登場する前は、オプションが限られていました。
このライブラリはRust用の低レベルAPIとPython用の高レベルインターフェースを提供します。JVMプロセスを起動せずに、数行のコードでS3バケットやローカルディスクにACID保証付きでデータを書き込むことができます。
PythonとRustでのクイックスタート
Pythonパッケージインターフェースdeltalakeは、開発者が何かを再学習する必要がないように設計されています。Pandas、Arrow、Polarsなどの馴染み深い分析ライブラリとうまく統合できます。
Pythonでのテーブルの書き込みと読み取りは、非常に馴染み深い見た目です:
import pandas as pd
from deltalake import DeltaTable, write_deltalake
# Создаем тестовый датафрейм и сохраняем его в формате Delta
df = pd.DataFrame({"id": [1, 2], "value": ["foo", "boo"]})
write_deltalake("./data/delta", df)
# Считываем данные обратно
dt = DeltaTable("./data/delta")
df_read = dt.to_pandas()
assert df.equals(df_read)
興味深い詳細として、Rustアプリケーションから同じテーブルを即座に開くことができます。手動のメタデータアセンブリは不要です。ライブラリは自動的に_delta_logディレクトリ内のJSONコミットログを解析します。
Rustでのテーブルメタデータ読み取りの例:
use deltalake::{open_table, DeltaTableError};
use url::Url;
#[tokio::main]
async fn main() -> Result<(), DeltaTableError> {
let delta_path = Url::from_directory_path("/abs/data/delta").unwrap();
let table = open_table(delta_path).await?;
let files: Vec<_> = table.get_file_uris()?.collect();
println!("{files:?}");
Ok(())
}
内部構造と統合
高速性と低メモリ消費は偶然ではありません。このプロジェクトはApache ArrowエンジンとDataFusionベクトルエンジンを基盤に構築されています。Rustは安全なメモリ管理と、クラウドストレージを操作する際の並列I/Oに使用されます。
このライブラリはAWS S3、Google Cloud Storage、Azure Blob Storage、ローカルファイルシステムと直接連携できます。
RustとArrowの共有基盤 덕분에、delta-rsは急速にモダンなデータ処理エコシステムの仲間入りを果たしました。人気のツールが箱から出してすぐに連携できます:
- PolarsはDeltaテーブルの直接読み書きにdelta-rsを使用します。
- DuckDBはDeltaログに対して分析SQLクエリを実行できます。
- Da、Dask、RayはPythonでの分散データ処理にこのモジュールを使用しています。
- AWS SDK for PandasはDelta形式のネイティブエンジンとして使用しています。
実践的なユースケース
どのような状況でdelta-rsはクラシックなアプローチに勝るでしょうか?
最初のケースはマイクロサービスアーキテクチャです。例えば、メッセージキューからイベントを収集し、5分ごとにデータストアにバッチを追加する必要があるRustまたはPythonサービスがあるとします。これのためにSparkクラスタを起動するのは費用対効果が高く、維持も複雑です。delta-rsを使用すれば、サービスは単にライブラリをリンクしてS3に直接データを書き込みます。
2番目のケースは軽量ETLパイプラインです。データ量が数十ギガバイトから数百ギガバイトの場合、Polarsとdelta-rsを組み合わせれば、PySparkクラスタがプロビジョニングされるよりも速く、単一インスタンスで処理できます。
3番目のケースはサーバーレドアーキテクチャです。イメージサイズと起動時間の制限が厳しいAWS Lambda関数では、Java環境を収めるのは問題があります。delta-rsを含むコンパイル済みRustバイナリはミリ秒単位で起動します。
このプロジェクトには制限がありますか?はい、Delta Lake仕様は非常に広範囲で、Databricksによって常に更新されています。一部の稀少または新しい形式機能は、delta-rsでは少し遅れて実装される場合があります。特定の条件を持つMERGEなどの複雑な操作を使用する前に、プロジェクトドキュメントのサポート機能テーブルを確認する必要があります。
結論
delta-ioチームは素晴らしい仕事をしました。ネイティブRustライブラリにより、Delta Lake形式の操作に軽量さを取り戻しました。
Parquetの上にトランザクション性、データバージョニング、信頼性の高いストレージが必要なのに、Javaインフラに触れたくない場合、ぜひdelta-rsを試してみてください。Pythonではコマンドpip install deltalakeでパッケージをインストールでき、Rustプロジェクトにはcargo add deltalakeで追加できます。
関連プロジェクト