2日遅れになってしまいましたが、、、
この記事は MicroAd Advent Calendar 2024 と Distributed computing (Apache Spark, Hadoop, Kafka, ...) Advent Calendar 2023 の1日目の記事です。
注: 執筆現在 2024/12/03 1:14
今年もアドカレの季節がやってきました🎄
今回は、DuckDBがIcebergに対応してたり、PyIcebergにDuckDBを見つけたので、どんなもんか試してみた。
はじめに
DuckDBについて
DuckDBはワンバイナリで動くので非常にお試ししやすく、拡張性も高い、軽くて速くて多機能なDBです。
基本的にインメモリで使うことが多いのですが、永続化も可能です。
個人的には、jsonファイルやParquetファイルをさくっと見たいときに使っています。 以下のようにして使えます。
JSONファイルだとざっくりこんな感じ。
duckdb -c "SELECT * FROM read_json_auto('./hoge.json');"
Parquetファイルだとデータやスキーマ、メタデータをちょろっと見たいときに重宝しています。
duckdb -c "SELECT * FROM read_parquet('data/yellow_tripdata_2024-01.parquet');" duckdb -c "SELECT * FROM parquet_schema('data/yellow_tripdata_2024-01.parquet');" duckdb -c "SELECT * FROM parquet_metadata('data/yellow_tripdata_2024-01.parquet');"
➕実行例(クリックして展開)
❯ duckdb -c "SELECT * FROM read_parquet('data/yellow_tripdata_2024-01.parquet');" ┌──────────┬──────────────────────┬──────────────────────┬───┬──────────────┬──────────────────────┬─────────────┐ │ VendorID │ tpep_pickup_datetime │ tpep_dropoff_datet… │ … │ total_amount │ congestion_surcharge │ Airport_fee │ │ int32 │ timestamp │ timestamp │ │ double │ double │ double │ ├──────────┼──────────────────────┼──────────────────────┼───┼──────────────┼──────────────────────┼─────────────┤ │ 2 │ 2024-01-01 00:57:55 │ 2024-01-01 01:17:43 │ … │ 22.7 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:03:00 │ 2024-01-01 00:09:36 │ … │ 18.75 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:17:06 │ 2024-01-01 00:35:01 │ … │ 31.3 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:36:38 │ 2024-01-01 00:44:56 │ … │ 17.0 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:46:51 │ 2024-01-01 00:52:57 │ … │ 16.1 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:54:08 │ 2024-01-01 01:26:31 │ … │ 41.5 │ 2.5 │ 0.0 │ │ 2 │ 2024-01-01 00:49:44 │ 2024-01-01 01:15:47 │ … │ 64.95 │ 0.0 │ 1.75 │ │ 1 │ 2024-01-01 00:30:40 │ 2024-01-01 00:58:40 │ … │ 30.4 │ 2.5 │ 0.0 │ │ 2 │ 2024-01-01 00:26:01 │ 2024-01-01 00:54:12 │ … │ 36.0 │ 2.5 │ 0.0 │ │ 2 │ 2024-01-01 00:28:08 │ 2024-01-01 00:29:16 │ … │ 8.0 │ 2.5 │ 0.0 │ │ 2 │ 2024-01-01 00:35:22 │ 2024-01-01 00:41:41 │ … │ 12.9 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:25:00 │ 2024-01-01 00:34:03 │ … │ 23.85 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:35:16 │ 2024-01-01 01:11:52 │ … │ 85.09 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:43:27 │ 2024-01-01 00:47:11 │ … │ 12.05 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:51:53 │ 2024-01-01 00:55:43 │ … │ 11.5 │ 2.5 │ 0.0 │ │ 1 │ 2024-01-01 00:50:09 │ 2024-01-01 01:03:57 │ … │ 25.45 │ 0.0 │ 1.75 │ │ 1 │ 2024-01-01 00:41:06 │ 2024-01-01 00:53:42 │ … │ 22.25 │ 2.5 │ 0.0 │ │ 2 │ 2024-01-01 00:52:09 │ 2024-01-01 00:52:28 │ … │ 8.0 │ 2.5 │ 0.0 │ │ 2 │ 2024-01-01 00:56:38 │ 2024-01-01 01:03:17 │ … │ 17.3 │ 2.5 │ 0.0 │ │ 2 │ 2024-01-01 00:32:34 │ 2024-01-01 00:49:33 │ … │ 32.7 │ 2.5 │ 0.0 │ │ · │ · │ · │ · │ · │ · │ · │ │ · │ · │ · │ · │ · │ · │ · │ │ · │ · │ · │ · │ · │ · │ · │ │ 1 │ 2024-01-31 23:22:09 │ 2024-01-31 23:33:41 │ … │ 17.1 │ │ │ │ 1 │ 2024-01-31 23:02:28 │ 2024-01-31 23:19:20 │ … │ 22.88 │ │ │ │ 2 │ 2024-01-31 23:33:02 │ 2024-01-31 23:43:41 │ … │ 17.97 │ │ │ │ 1 │ 2024-01-31 23:01:47 │ 2024-01-31 23:08:51 │ … │ 16.45 │ │ │ │ 2 │ 2024-01-31 23:46:39 │ 2024-01-31 23:57:31 │ … │ 19.73 │ │ │ │ 1 │ 2024-01-31 23:40:27 │ 2024-01-31 23:54:56 │ … │ 61.16 │ │ │ │ 2 │ 2024-01-31 23:49:00 │ 2024-02-01 00:08:00 │ … │ 32.78 │ │ │ │ 1 │ 2024-01-31 23:01:28 │ 2024-01-31 23:20:46 │ … │ 25.91 │ │ │ │ 1 │ 2024-01-31 23:52:57 │ 2024-01-31 23:56:48 │ … │ 11.61 │ │ │ │ 2 │ 2024-01-31 23:16:55 │ 2024-01-31 23:57:34 │ … │ 118.96 │ │ │ │ 2 │ 2024-01-31 23:23:02 │ 2024-01-31 23:37:53 │ … │ 24.25 │ │ │ │ 1 │ 2024-01-31 23:54:30 │ 2024-02-01 00:01:05 │ … │ 16.32 │ │ │ │ 2 │ 2024-01-31 23:40:02 │ 2024-01-31 23:47:45 │ … │ 19.85 │ │ │ │ 2 │ 2024-01-31 23:27:00 │ 2024-01-31 23:43:00 │ … │ 47.09 │ │ │ │ 1 │ 2024-01-31 23:18:48 │ 2024-01-31 23:38:05 │ … │ 30.93 │ │ │ │ 2 │ 2024-01-31 23:45:59 │ 2024-01-31 23:54:36 │ … │ 21.77 │ │ │ │ 1 │ 2024-01-31 23:13:07 │ 2024-01-31 23:27:52 │ … │ 25.74 │ │ │ │ 2 │ 2024-01-31 23:19:00 │ 2024-01-31 23:38:00 │ … │ 23.97 │ │ │ │ 2 │ 2024-01-31 23:07:23 │ 2024-01-31 23:25:14 │ … │ 33.46 │ │ │ │ 1 │ 2024-01-31 23:58:25 │ 2024-02-01 00:13:30 │ … │ 55.88 │ │ │ ├──────────┴──────────────────────┴──────────────────────┴───┴──────────────┴──────────────────────┴─────────────┤ │ 2964624 rows (40 shown) 19 columns (6 shown) │ └────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ❯ duckdb -c "SELECT * FROM parquet_schema('data/yellow_tripdata_2024-01.parquet');" ┌──────────────────────┬──────────────────────┬────────────┬───┬───────┬───────────┬──────────┬──────────────────────┐ │ file_name │ name │ type │ … │ scale │ precision │ field_id │ logical_type │ │ varchar │ varchar │ varchar │ │ int64 │ int64 │ int64 │ varchar │ ├──────────────────────┼──────────────────────┼────────────┼───┼───────┼───────────┼──────────┼──────────────────────┤ │ data/yellow_tripda… │ schema │ │ … │ │ │ │ │ │ data/yellow_tripda… │ VendorID │ INT32 │ … │ │ │ │ │ │ data/yellow_tripda… │ tpep_pickup_datetime │ INT64 │ … │ │ │ │ TimestampType(isAd… │ │ data/yellow_tripda… │ tpep_dropoff_datet… │ INT64 │ … │ │ │ │ TimestampType(isAd… │ │ data/yellow_tripda… │ passenger_count │ INT64 │ … │ │ │ │ │ │ data/yellow_tripda… │ trip_distance │ DOUBLE │ … │ │ │ │ │ │ data/yellow_tripda… │ RatecodeID │ INT64 │ … │ │ │ │ │ │ data/yellow_tripda… │ store_and_fwd_flag │ BYTE_ARRAY │ … │ │ │ │ StringType() │ │ data/yellow_tripda… │ PULocationID │ INT32 │ … │ │ │ │ │ │ data/yellow_tripda… │ DOLocationID │ INT32 │ … │ │ │ │ │ │ data/yellow_tripda… │ payment_type │ INT64 │ … │ │ │ │ │ │ data/yellow_tripda… │ fare_amount │ DOUBLE │ … │ │ │ │ │ │ data/yellow_tripda… │ extra │ DOUBLE │ … │ │ │ │ │ │ data/yellow_tripda… │ mta_tax │ DOUBLE │ … │ │ │ │ │ │ data/yellow_tripda… │ tip_amount │ DOUBLE │ … │ │ │ │ │ │ data/yellow_tripda… │ tolls_amount │ DOUBLE │ … │ │ │ │ │ │ data/yellow_tripda… │ improvement_surcha… │ DOUBLE │ … │ │ │ │ │ │ data/yellow_tripda… │ total_amount │ DOUBLE │ … │ │ │ │ │ │ data/yellow_tripda… │ congestion_surcharge │ DOUBLE │ … │ │ │ │ │ │ data/yellow_tripda… │ Airport_fee │ DOUBLE │ … │ │ │ │ │ ├──────────────────────┴──────────────────────┴────────────┴───┴───────┴───────────┴──────────┴──────────────────────┤ │ 20 rows 11 columns (7 shown) │ └────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ❯ duckdb -c "SELECT * FROM parquet_metadata('data/yellow_tripdata_2024-01.parquet');" ┌──────────────────────┬──────────────┬────────────────────┬───┬──────────────────────┬────────────────────┐ │ file_name │ row_group_id │ row_group_num_rows │ … │ total_uncompressed… │ key_value_metadata │ │ varchar │ int64 │ int64 │ │ int64 │ map(blob, blob) │ ├──────────────────────┼──────────────┼────────────────────┼───┼──────────────────────┼────────────────────┤ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 158152 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 8176913 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 8179919 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 465055 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 1605038 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 206218 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 14615 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 1051681 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 1182839 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 257706 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 1459439 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 683722 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 113415 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 1601737 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 657008 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 75733 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 1946946 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 203031 │ {} │ │ data/yellow_tripda… │ 0 │ 1048576 │ … │ 197970 │ {} │ │ data/yellow_tripda… │ 1 │ 1048576 │ … │ 158172 │ {} │ │ · │ · │ · │ · │ · │ · │ │ · │ · │ · │ · │ · │ · │ │ · │ · │ · │ · │ · │ · │ │ data/yellow_tripda… │ 1 │ 1048576 │ … │ 187324 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 207984 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 6507984 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 6509968 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 309331 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 1330132 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 121289 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 10225 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 870250 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 978731 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 235336 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 1301308 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 505230 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 76631 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 1291579 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 427940 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 43934 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 1629305 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 164214 │ {} │ │ data/yellow_tripda… │ 2 │ 867472 │ … │ 123092 │ {} │ ├──────────────────────┴──────────────┴────────────────────┴───┴──────────────────────┴────────────────────┤ │ 57 rows (40 shown) 24 columns (5 shown) │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
今年は書籍も出版されて勢いがあるプロダクトです。
PyIcebergについて
PyIcebergは、IcebergをPython使って操作することできるライブラリです。
pipでインストールすると、pyicebergってCLIも同梱されてテーブルやスキーマの状態を確認する際に便利です。
v0.6.からは書き込みもサポートされているので、Sparkも使わずにPythonコードで直接テーブル操作ができるようになっています。
DaftやRay1がIcebergをサポートしたので、本格的にPythonだけで分散データ処理ができそうです。
DuckDBのIcebergサポートについて
概要説明
DuckDBはIceberg拡張が公式でサポートされています。
ただし、現状のDuckDBでは書き込みが出来ないので注意が必要です。
なぜならIceberg設定にカタログ情報がないことからも書き込みが出来ないことが分かります。カタログに接続出来ないので、Namespace(Schema)やテーブル一覧が取れません。
そのため、テーブルごとにメタデータ含めたテーブルのパス(例: s3://⟨bucket⟩/⟨namespace⟩/⟨table⟩
)を指定する必要があります。
また、スナップショットやメタデータといったメタデータ層が参照できません。 DuckDB自体には以下のように用意されているものの、、、
SELECT * FROM iceberg_snapshots('s3://⟨bucket⟩/⟨namespace⟩/⟨table⟩');
SELECT * FROM iceberg_metadata('s3://⟨bucket⟩/⟨namespace⟩/⟨table⟩', allow_moved_paths = true);
実行すると以下のエラーになります。
HTTP Error: Unable to connect to URL "http://⟨endpoint⟩/⟨bucket⟩/⟨namespace⟩/⟨table⟩/metadata/version-hint.text": 404 (Not Found)
version-hint.text
から推測出来るように、DuckDBのメタデータの参照はファイルシステムを使った Hadoopカタログ2 が前提となっているためです。
試す際のハマりポイント
HTTP PROXY対策
HTTP PROXYな人は拡張機能を追加する際に対策が必要です。
まず拡張機能を追加する前に以下のようにproxyの設定が必要です。
-- proxy設定追加 SET GLOBAL http_proxy = "proxy.example.com:8080" ; -- 設定状況の確認 SELECT current_setting('http_proxy'); SELECT * from duckdb_settings() WHERE name ILIKE '%proxy' ;
間違った場合 & いらなくなった場合は以下のようにRESTコマンド使って空にしてから再度SETしてください。
RESET GLOBAL http_proxy ;
proxyの対策が出来たところで以下のように拡張機能をインストールしてください。インストールは1度だけでOK。
INSTALL iceberg ; INSTALL httpfs;
また、拡張機能を更新したい場合は以下で更新します。
UPDATE EXTENSIONS (iceberg); UPDATE EXTENSIONS (httpfs);
Icebergテーブルを参照したい場合は、利用する直前でLOADしてください。
LOAD iceberg; LOAD httpfs;
拡張機能がインストールまたはLOAD出来ているかは以下で確認出来ます。
SELECT * FROM duckdb_extensions() WHERE extension_name = 'httpfs' OR extension_name = 'iceberg';
S3互換ストレージ向けの接続設定
Hadoopカタログを使ってファイルシステムに直接作成しているIcebergテーブルの場合は以下のようにデータのパスを指定するだけなので簡単です
SELECT count(*) FROM iceberg_scan('data/iceberg/lineitem_iceberg', allow_moved_paths = true);
ただし、S3などリモートにデータがある場合は、クエリ実行前にS3バケットの接続情報を格納する必要があります。また、MinIOやApache Ozone、DELL ECSなどS3互換ストレージにも対応しています。
以下の例は、MinIOを例にS3互換ストレージの場合の設定になります。
CREATE SECRET s3 ( TYPE S3, KEY_ID "AK********", SECRET "**********", REGION "us-east-1", ENDPOINT 'minio:9000', URL_STYLE 'path', USE_SSL false );
💡 残念ながらENVは指定出来ないです(${ENV:AWS_ACCESS_KEY_ID}
のように指定できたらなぁ )
💡 ENDPOINTの設定値に http://
などのプロトコルは不要
詳しい情報は以下を参照ください。
PyIcebergのDuckDBサポートについて
概要説明
次に、PyIcebergが、どのようにDuckDBをサポートしているかについて。
Icebergテーブルをスキャンした結果をインメモリのDuckDB上でクエリ出来ます(事前にDuckDBのインストールは必須)。
以下は、Namespace ice_db
のテーブル yellow_tripdata
の一部をDuckDBテーブル distant_taxi_trips
に変換して、DuckDBテーブルとしてクエリしています。
from pyiceberg.expressions import GreaterThanOrEqual from pyiceberg.catalog import load_catalog # defaultのカタログを指定 catalog = load_catalog('default') # Icebergテーブルを読み込み table = catalog.load_table('ice_db.yellow_tripdata') # スキーマ情報を出力 print("Schema:") print(table.schema()) # 一部のデータにフィルタして、インメモリのDuckDBに変換 con = table.scan( row_filter=GreaterThanOrEqual("trip_distance", 10.0), selected_fields=("vendorid", "tpep_pickup_datetime", "tpep_dropoff_datetime"), case_sensitive=True ).to_duckdb(table_name="distant_taxi_trips") # 変換したDuckDBテーブル側でSQLクエリを実行 print( con.execute( """ SELECT tpep_dropoff_datetime - tpep_pickup_datetime AS duration FROM distant_taxi_trips LIMIT 4 """ ).fetchall() )
参考:Pythonのdependencies
python = "^3.11" pyiceberg = {extras = ["duckdb", "pyarrow", "s3fs"], version = "^0.8.0"} requests = "^2.32.3"
PyIcebergのDuckDB対応の詳細は以下を参照ください。
API to_duckdb
の詳細については以下を参照ください。
PyIcebergのハマりポイント
.pyiceberg.yaml の置き場所に注意
以下のドキュメントに記載があるように PyIcebergの設定ファイル .pyiceberg.yaml
は、デフォルト ~/.pyiceberg.yaml
となります。
プロジェクトごとに変えたい場合は、環境変数 PYICEBERG_HOME
を使って .pyiceberg.yaml
のあるディレクトを指定してくだい。
🫠 PyIcebergを使うPythonスクリプトを実行するディレクトリ直下に置いても読み込まないので注意!
S3互換ストレージ向けの .pyiceberg.yaml の設定
S3互換ストレージについて、パスのスタイルが仮想ホストでない場合は以下のように s3.path-style-access
と s3.endpoint
の指定が必要になります。
catalog: default: type: rest uri: http://iceberg-rest:8181 s3.path-style-access: true s3.endpoint: http://minio:9000 s3.access-key-id: AK******** s3.secret-access-key: *******
使いどころを考える🤔
テーブルを一部のデータにフィルタして、インメモリのDuckDBに変換し、
con = table.scan( row_filter=GreaterThanOrEqual("trip_distance", 10.0), selected_fields=("vendorid", "tpep_pickup_datetime", "tpep_dropoff_datetime"), case_sensitive=True ).to_duckdb(table_name="distant_taxi_trips")
変換したDuckDBテーブル側でSQLクエリを実行する。
print( con.execute( """ SELECT tpep_dropoff_datetime - tpep_pickup_datetime AS duration FROM distant_taxi_trips LIMIT 4 """ ).fetchall() )
データマートの集計テーブルに対してアドホックに分析したい場合には便利かもしれない。。。
惜しいのは、DuckDBテーブルへの変換はインメモリのみのサポートとなっている点。
DuckDB自体は以下のように独自のフォーマットのファイルを使って永続化することは可能です。なので、 to_duckdb(table_name="distant_taxi_trips", persistent_database=True)
みたいに永続化のオプションが出来たら欲しい断面だけDuckDBテーブルに変換して、あとは手元でDuckDBからSQLクエリでアドホックに分析とか出来たら化けそう。
DuckDB側のPython APIには、File-Based Connection が以下の通り利用可能です。
PyIceberg側のコード見るとインメモリ決め打ちになっていることが分かります。
https://github.com/apache/iceberg-python/blob/68e17af746021f630b7efa38a50b3ffb51a2dad8/pyiceberg/table/init.py#L1481
def to_duckdb(self, table_name: str, connection: Optional[DuckDBPyConnection] = None) -> DuckDBPyConnection: """Shorthand for loading the Iceberg Table in DuckDB. Returns: DuckDBPyConnection: In memory DuckDB connection with the Iceberg table. """ import duckdb con = connection or duckdb.connect(database=":memory:") con.register(table_name, self.to_arrow()) return con
(´-`).。oO(あれ?コミットチャンスでは、、)
最後に
いかがだったでしょうか。
DuckDBはIcebergからの利用以外にも幅広く便利に使えるとてもおもしろいプロダクトです。これからも使ってみて何か出てきたら取り上げていきます。
以上、MicroAd Advent Calendar 2024 と Distributed computing (Apache Spark, Hadoop, Kafka, ...) Advent Calendar 2024 の1日目の記事でした。
さーて、アドカレ2日目の記事は、、、
MicroAd Advent Calendar 2024 は、Knativeでトラフィック制御。 そして、Distributed computing Advent Calendar 2024 は、Apache NiFi 2.0についてとなっています。
どちらも楽しみですね!
補足
元ネタ
distant_taxi_tripsテーブルのテーブル情報
https://www.nyc.gov/assets/tlc/downloads/pdf/data_dictionary_trip_records_yellow.pdf
distant_taxi_tripsテーブルのレコードデータは、以下のYellow Taxi Trip Recordsを取得してIcebergテーブルを作成してます。
-
RayはPythonベースのOSSの分散処理フレームワークです。
docs.ray.io
また、Daftはデータエンジニアリング、データ分析、ML/AIのための統合データエンジンです。DaftはSQLとPythonのDataFrameインターフェースをネイティブにサポートしていてRustで開発されています。また、DaftはRayネイティブにサポートすることによって分散DataFrameワークロードを大規模に実行できるらしいです。
www.getdaft.io↩ -
詳しくはApache Iceberg: The Definitive Guideの第5章 p100 を参照ください。
www.oreilly.com
Dremio様からダウンロードも出来ます。
hello.dremio.com↩