Mímisbrunnr知恵の泉

← データエンジニアリング 一覧

🎓 レベル:発展 | 重要度:B(推奨)

📎 前提:列指向ストレージと分析クエリ | 関連:データレイクとオブジェクトストレージレイクハウスとテーブルフォーマット

要点(BLUF)

概念 ── 「どう並べて、どう書き出すか」

シリアライゼーションとは、メモリ上のデータ(テーブル・オブジェクト)をファイルやネットワークに流せるバイト列に変換すること。逆がデシリアライズ。CSVもParquetも「テーブル→バイト列」の方法ですが、並べ方(行/列)・圧縮・スキーマの持ち方が違い、それが性能と運用を大きく分けます。

flowchart TB
    CSV["CSV / JSON:人間可読・行指向・型曖昧・大きい"]
    AVRO["Avro:行指向・スキーマ同梱・進化に強い・ストリーム向き"]
    PARQ["Parquet / ORC:列指向・高圧縮・統計付き・分析向き"]

仕組み ── 三つの軸で比べる

形式並べ方圧縮スキーマ得意
CSVほぼなしなし(全部文字列)受け渡し・少量・目視
JSON行(入れ子可)ほぼなしなし(自己記述的)API・半構造データ
Avroありファイルに同梱・進化に強いストリーム・取り込み
Parquet高い(列ごと)同梱・統計付き分析・DWH・レイク
ORC高い同梱・統計付き分析(Hadoop系)

動くSQL/変換例 ── CSV vs Parquet を実測

同じ5万行を CSV と Parquet で書き出し、サイズと「1列だけ読む」を比べます。

import pandas as pd
df = pd.DataFrame({"id": range(50000),
                   "region": ["East","West","North","South"]*12500,
                   "amount": [(i*7) % 1000 for i in range(50000)]})
df.to_csv("data.csv", index=False)
df.to_parquet("data.parquet", index=False)        # pyarrow + snappy 圧縮
only = pd.read_parquet("data.parquet", columns=["amount"])  # 必要列だけ読む
print(int(only["amount"].sum()))

実行結果(実機):

行数: 50000
CSV     :    789.5 KB
Parquet :    305.4 KB  (圧縮率 2.6 倍)
Parquetから amount 列だけ読込 -> shape=(50000, 1), 合計=24975000

Parquetは同じデータでCSVの約2.6分の1のサイズ(regionのような繰り返し文字列がよく圧縮される)。さらに columns=["amount"]他の列を一切読まずに合計を計算できます。これが 列指向ストレージと分析クエリ の「必要な列だけI/O」の実物です。

なぜそうするか ── 読み方に形式を合わせる

なぜ「分析はParquet、ストリームはAvro」なのか。データの使われ方に物理形式を合わせるのが原則だからです。分析は「大量行・少数列・一括書き」なので、列指向で高圧縮なParquetが最適。ストリーム取り込みは「1件ずつ来る・全列まとめて書く・スキーマが進化する」ので、行指向でスキーマ進化に強いAvroが向く。CSVは「とりあえず受け渡す」用途には便利でも、型が無く圧縮も効かないため、基盤の中核に据えると後で苦労します。

⚠️ よくある落とし穴

対応ラボ

data-engineering-study/labs/03_sql_optimization.pyPYTHONIOENCODING=utf-8 で実行・CSV/Parquetサイズと列読みを確認済み)。

関連

第3章 SQLとクエリ最適化 目次