Rindrics Mumbles

ローカル必須要件下でのデータパイプライン構築

とある研究者の方から分析環境構築について相談を受けた。 アーキテクチャ設計 & データパイプライン構築を支援したのでメモしておく。

要求

受けた相談としては下記の通り

  • サイズの大きいデータセットを解析したい
  • データセットがフォルダ・ファイルに分かれていて圧倒されている
  • 解析には R を使いたい

ヒアリングしてみたところ、アーキテクチャの決定に関わる重要な情報が得られた。

  • データ形式: 特定区切り文字の ASCII ファイル
    • データベースから抽出されたプレーンテキストファイルで、区切り文字は “#
  • データサイズ: 1 年あたり 1.6 GB のデータが 20 年分
    • Web サービスが生成するビジネスデータのサイズに比べると特別大きくはないものの、研究データとしてはかなり充実している部類
    • R で直接解析するのは厳しいと判断した(贅沢な悩みですね)
    • この時点で、まず DWH が必要であることがわかった
  • 解析には R を使いたい」の must 感: must ではない
    • メイン解析前の探索的解析において R から透過的に DWH を操作するにしても、可視化時にはデータをメモリに載せる必要がある
      • それもちょっと厳しそうなので、探索解析における可視化には何らかの BI ツールを使うことにした
  • データ更新の有無: あり
    • 既存のデータが修正されることがあるとのこと。ただし更新履歴を記録する必要はなく、上書きでよい。これはかなり助かる
  • オンラインサービス・有料サービスの利用可否: どちらも利用不可
    • となると、定番スタックからはやや離れたツール選定が必要になる可能性が想定された。
      • 裏を返せばそもそもの選択肢が狭まってある意味では楽かもしれない、、、?
      • 参照できる既往知見がだいぶ減るのはキツいが致し方なし
    • ちなみにオンライン不可というのはインターネットへのアクセス自体が不可という意味ではなかった

要件

ということで、ヒアリングの結果見えた要件は下記の通り:

  • オフラインで動く 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

ポイント

  • 実行にそれなりの時間がかかるので、ユースケースを通せるまでターゲットディレクトリは絞っておく
  • 全カラムをいったん string でロードしておく
    • ゴミデータが入っているとパースエラーになったりするので、始めからデータ仕様書通りの型に合わせに行かない
  • .duckdb の生成先を superset-duckdb/data 配下にしておく
[destination.filesystem] # in ./dlt/secrets.toml
bucket_url="file://path/to/superset-duckdb/data"

DuckDB

特に問題なし

Superset

ポイント

  • DLT によるロードで生成される .duckdbsuperset-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

comments powered by Disqus