ローカル必須要件下でのデータパイプライン構築
とある研究者の方から分析環境構築について相談を受けた。 アーキテクチャ設計 & データパイプライン構築を支援したのでメモしておく。
要求
受けた相談としては下記の通り
- サイズの大きいデータセットを解析したい
- データセットがフォルダ・ファイルに分かれていて圧倒されている
- 解析にはRを使いたい
ヒアリングしてみたところ、アーキテクチャの決定に関わる重要な情報が得られた。
- データ形式: 特定区切り文字のASCIIファイル
- データベースから抽出されたプレーンテキストファイルで、区切り文字は “
#”
- データベースから抽出されたプレーンテキストファイルで、区切り文字は “
- データサイズ: 1年あたり1.6 GBのデータが20年分
- Webサービスが生成するビジネスデータのサイズに比べると特別大きくはないものの、研究データとしてはかなり充実している部類
- Rで直接解析するのは厳しいと判断した(贅沢な悩みですね)
- この時点で、まずDWHが必要であることがわかった
- 解析にはRを使いたい」のmust感: mustではない
- メイン解析前の探索的解析においてRから透過的にDWHを操作するにしても、可視化時にはデータをメモリに載せる必要がある
- それもちょっと厳しそうなので、探索解析における可視化には何らかのBIツールを使うことにした
- メイン解析前の探索的解析においてRから透過的にDWHを操作するにしても、可視化時にはデータをメモリに載せる必要がある
- データ更新の有無: あり
- 既存のデータが修正されることがあるとのこと。ただし更新履歴を記録する必要はなく、上書きでよい。これはかなり助かる
- オンラインサービス・有料サービスの利用可否: どちらも利用不可
- となると、定番スタックからはやや離れたツール選定が必要になる可能性が想定された。
- 裏を返せばそもそもの選択肢が狭まってある意味では楽かもしれない、、、?
- 参照できる既往知見がだいぶ減るのはキツいが致し方なし
- ちなみにオンライン不可というのはインターネットへのアクセス自体が不可という意味ではなかった
- となると、定番スタックからはやや離れたツール選定が必要になる可能性が想定された。
要件
ということで、ヒアリングの結果見えた要件は下記の通り:
- オフラインで動くOSSのDWHを使うこと
- ファイルに更新があるたびDWHにloadできること
- オフラインで動くOSSのBIツールを使うこと
- BIツール用にデータマートを準備できること
アーキテクチャ設計・ツール選定
(E)LT形式とする
- load: DLT
- DWH: DuckDB
- transform: dbt (core)
- BI: Superset (Docker container)
- はじめRill Dataで試したのだがデータ量が多すぎたようでとても操作できなかった
flowchart LR
subgraph dataset
datasets@{ shape: docs, label: "dataset.txt"}
end
DLT[DLT] -.-> |read| dataset
DLT ---> |load| duckdb[(dataset.duckdb)]
dbt -.-> |read| duckdb
dbt --> |transform| duckdb
Superset -.-> |read| duckdb
各ツールを利用した実装のポイント
Prerequisits:
DLT
- source:
filesystemタイプ - target: DuckDB
ポイント
- 実行にそれなりの時間がかかるので、ユースケースを通せるまでターゲットディレクトリは絞っておく
- 全カラムをいったんstringでロードしておく
- ゴミデータが入っているとパースエラーになったりするので、始めからデータ仕様書通りの型に合わせに行かない
.duckdbの生成先をsuperset-duckdb/data配下にしておく
[destination.filesystem] # in ./dlt/secrets.toml
bucket_url="file://path/to/superset-duckdb/data"
DuckDB
特に問題なし
Superset
- この記事を参考に、
jorritsandbrink/superset-duckdb相当のイメージをビルドして使った。 - https://github.com/jorritsandbrink/superset-duckdbをcloneしておく
ポイント
- DLTによるロードで生成される
.duckdbがsuperset-duckdb/data配下に置かれるようにしておくdocker run時にマウントしてくれるのでdbtによるtransform結果を都度確認するのが楽
dbt
データ仕様書を参考に、各テーブルから利用したいカラムを型変換しつつDuckDBにリロードする
Makefile
データの更新頻度はそれほど高くないので(年に数回程度)、パイプライン実行は手動でやっている。
.PHONY: load
load:
uv run load.py # DLTによるload処理を書いたファイル
.PHONY: superset
superset:
cd superset-duckdb && \
docker build -t YOURNAME/superset-duckdb docker && \
docker run -d -p 8080:8088 \
-e "SUPERSET_SECRET_KEY=your_secret_key" \
--mount type=bind,source=$$(pwd)/data,target=/data \
--name superset-duckdb \
YOURNAME/superset-duckdb && \
./docker/setup.sh
.PHONY: transform
transform:
uv run dbt run --profiles-dir .dbt --project-dir PROJECT_DIR