45395 - シコウサクゴ -

Parquetファイルをデータパイプラインの中間形式に選んだ理由

2026-04-03
AI駆動開発
AI駆動開発
Parquet
データパイプライン
Python
pandas
Last updated:2026-04-05
8 Minutes
1587 Words

自動化プロジェクトのデータパイプラインで、長らくCSVを中間形式として使っていました。しかし、411カラム x 10データソース x 8集計期間という規模になると、CSVの限界が顕著になりました。

  • 型の曖昧さ: 数値カラムが文字列として読み込まれる
  • 読み込み速度: 全カラムを毎回パースする無駄
  • ファイルサイズ: 圧縮なしのテキストで数GB

本記事では、CSVからParquetへの移行で得られた具体的な改善と、移行時に踏んだ落とし穴を記録します。


CSVの何が問題だったか

型の消失

CSVはプレーンテキストなので、全ての値が文字列として保存されます。

1
import pandas as pd
2
3
# CSVに書き出し
4
df = pd.DataFrame({"value": [145.50, 146.20], "count": [1000, 2000]})
5
df.to_csv("data.csv", index=False)
6
7
# CSVから読み込み → 型が変わることがある
8
df_loaded = pd.read_csv("data.csv")
9
print(df_loaded.dtypes)
10
# value float64 ← たまたま正しい
11
# count int64 ← たまたま正しい
12
13
# しかし、欠損値があると...
14
df2 = pd.DataFrame({"value": [145.50, None], "count": [1000, None]})
15
df2.to_csv("data2.csv", index=False)
4 collapsed lines
16
df2_loaded = pd.read_csv("data2.csv")
17
print(df2_loaded.dtypes)
18
# value float64
19
# count float64 ← intがfloatに変わった

411カラムのうち、どのカラムの型が変わったかを追跡するのは現実的ではありません。

全カラム読み込みの無駄

分析パイプラインでは「411カラムのうち10カラムだけ使う」ケースが大半です。CSVでは全カラムをパースしてからフィルタします。

1
# CSV: 411カラム全部読んでからフィルタ
2
df = pd.read_csv("analysis.csv") # 全カラムパース(遅い)
3
df = df[["timestamp", "metric_a", "metric_b"]] # 使うのは3カラムだけ

Parquetを選んだ4つの理由

1. 列指向フォーマット

Parquetは列指向(columnar)フォーマットです。必要な列だけを物理的に読み込めます。

1
import pandas as pd
2
3
# Parquet: 必要な列だけ読み込み(高速)
4
df = pd.read_parquet(
5
"analysis_results.parquet",
6
columns=["timestamp", "metric_a", "metric_b"]
7
)

411カラムから10カラムだけ読む場合、理論上は約40分の1のI/Oで済みます。実測でもCSVの3〜5倍高速でした。

2. スキーマ保存

型情報がファイル自体に埋め込まれます。「数値が文字列に化ける」問題が構造的に発生しません。

1
import pyarrow.parquet as pq
2
3
# 書き込み(型情報付き)
4
df.to_parquet("analysis_results.parquet", engine="pyarrow")
5
6
# スキーマ確認
7
schema = pq.read_schema("analysis_results.parquet")
8
print(schema)
9
# timestamp: double
10
# metric_a: double
11
# metric_b: double
12
# result_label: string
13
# ... 型情報が保存されている

スキーマがファイルに埋め込まれているため、読み込み側でdtypeを指定する必要がありません。パイプラインの下流で「この列は本当にfloatか?」と心配しなくて済みます。

3. 圧縮効率

Parquetはsnappy圧縮をデフォルトで使用します。テキストベースのCSVと比較して、1/5〜1/10のファイルサイズになります。

1
import os
2
3
# 同じデータをCSVとParquetで保存して比較
4
df.to_csv("data.csv", index=False)
5
df.to_parquet("data.parquet", engine="pyarrow", compression="snappy")
6
7
csv_size = os.path.getsize("data.csv")
8
parquet_size = os.path.getsize("data.parquet")
9
print(f"CSV: {csv_size / 1024 / 1024:.1f} MB")
10
print(f"Parquet: {parquet_size / 1024 / 1024:.1f} MB")
11
print(f"圧縮率: {parquet_size / csv_size:.1%}")
12
# 実測: CSV 230MB → Parquet 28MB(約12%)

4. pandas互換

移行コストが極めて低いです。to_csv()to_parquet()に変えるだけで基本的に動きます。

1
# Before
2
df.to_csv("output.csv", index=False)
3
df = pd.read_csv("output.csv")
4
5
# After
6
df.to_parquet("output.parquet", engine="pyarrow")
7
df = pd.read_parquet("output.parquet")

実データの規模感

本番システムで扱うデータの規模は以下の通りです。

1
411カラム(分析指標)
2
x 10データソース
3
x 8集計期間(1H, 2H, 4H, 6H, 8H, 12H, D, W)
4
= 約32,880カラム相当のデータ量

このスケールでCSVを使い続けることは、I/O・型安全性・ストレージの全ての面で非合理でした。


BIツール対応:Version 8.4の改善

Parquetへの移行に合わせて、BIツール(Metabase等)との連携を考慮したカラム設計も行いました。

ReferenceDate列の追加

1
from datetime import datetime
2
3
4
def add_reference_columns(df: pd.DataFrame, source: str, period: str) -> pd.DataFrame:
5
"""BIツール連携用のメタデータカラムを追加する。"""
6
df = df.copy()
7
df["ReferenceDate"] = datetime.now().strftime("%Y-%m-%d")
8
df["Source"] = source
9
df["Period"] = period
10
return df

複合IDカラム

各レコードを一意に識別するための複合IDを追加しました。

1
from datetime import datetime
2
3
4
def generate_composite_id(
5
reference_date: str,
6
source: str,
7
period: str,
8
sequence: int,
9
) -> str:
10
"""複合IDを生成する。
11
12
形式: {YYYYMMDD}_{Source}_{Period}_{YYYYMMDDHHMM}_{00001-99999}
13
例: 20260327_SRC001_4H_202603271500_00001
14
"""
15
now = datetime.now().strftime("%Y%m%d%H%M")
1 collapsed line
16
return f"{reference_date}_{source}_{period}_{now}_{sequence:05d}"

落とし穴:ファイル命名規則変更によるインシデント

Parquet移行時に最大の問題を引き起こしたのは、ファイル命名規則の変更でした。

何が起きたか

1
Before: analysis_SRC001_4H_20260301.csv
2
After: analysis_results_SRC001_4H_20260301.parquet

拡張子だけでなく、ファイル名のプレフィックスも変更しました。その結果、下流パイプラインの20以上のスクリプトでファイルが見つからなくなりました。

対策:IMPACT_ANALYSISの必須化

この経験から、データパイプラインのファイル形式変更には必ずIMPACT_ANALYSISを実施するルールを追加しました。

1
## IMPACT_ANALYSIS 必須チェック項目(データ形式変更時)
2
3
1. このファイルを読み込んでいるスクリプトの一覧
4
2. ファイル名パターンをハードコードしている箇所
5
3. 拡張子でフィルタしている箇所(*.csv → *.parquet)
6
4. バックアップスクリプトの対象パターン
7
5. CI/CDパイプラインの成果物パス

ファイル命名規則の変更は「コード変更」ではなく「インフラ変更」として扱うべきです。


学んだこと

1. CSVからParquetへの移行は型安全性の向上が最大の利点

パフォーマンスや圧縮率も重要ですが、最大の利点は「型が勝手に変わらない」安心感です。411カラムの型を毎回確認する必要がなくなりました。

2. 列指向は分析パイプラインに最適

「全行を読むが、一部の列だけ使う」という分析パイプラインの典型的なアクセスパターンに、列指向フォーマットは理想的にマッチします。

3. ファイル命名規則はIMPACT_ANALYSISの対象

データ形式の変更は、コードの変更よりも広範囲に影響します。ファイル名・パス・拡張子の変更は、必ず下流の全スクリプトを洗い出してから実施すべきです。


まとめ

ParquetをCSVの代替として採用する判断で重要なのは以下の3点です。

  1. 型安全性が最大の利点: スキーマがファイルに埋め込まれ、読み込み時の型変化が構造的に防がれます
  2. 列指向の読み込み効率: 411カラム中10カラムだけ読む場合、CSVの3〜5倍高速です
  3. 移行時はファイル命名規則に注意: 拡張子やプレフィックスの変更は下流パイプライン全体に影響します。IMPACT_ANALYSISを必ず実施してください
Article title:Parquetファイルをデータパイプラインの中間形式に選んだ理由
Article author:45395
Release time:2026-04-03

記事へのご質問・ご感想をお聞かせください

フィードバックを送る