DEA / ドメイン1 データの取り込みと変換
重要な内容
データ形式と形式の変換
データをどの形式で保存するかで、クエリの速さ、スキャン量の料金、ストレージの費用が大きく変わります。DEA では「CSV を に変換する」が繰り返し出題されます。この章では、主な形式の違い (行指向と列指向)、圧縮と分割可能性、そして形式を変換する方法を整理します。
Point
- 行指向は1行ぶんのデータを続けて保存する形式 (CSV、JSON、Avro)、列指向は1列ぶんのデータを続けて保存する形式 (Parquet、ORC) です。
- 分割可能 (splittable) は、1つのファイルを途中から読み始められ、複数のワーカーで分けて処理できる性質です。
- 和訳
- Columnar: 列の、円柱状の
- Weblio英和辞書「columnar」
概要
分析のクエリは「多くの行の、少しの列」を読むことがほとんどです。列指向の形式なら、必要な列だけを読み、同じ型の値が並ぶため圧縮もよく効きます。 や はスキャンしたデータ量で課金されるため、列指向にして圧縮すると、速く、安くなります。
| 形式 | 指向 | スキーマ | 主な用途 |
|---|---|---|---|
| CSV | 行 | なし (ヘッダー行程度) | 受け渡し、表計算ソフト、小さなデータ |
| 行 | 自己記述的 (入れ子あり) | 、ログ、半 | |
| 行 | ファイルにスキーマを持つ | ストリーミング、行単位の書き込み、スキーマの進化 | |
| 列 | ファイルにスキーマを持つ | 分析 (Athena、Redshift Spectrum、) | |
| 列 | ファイルにスキーマを持つ | 分析 (Hive 由来、Athena、) |
主要技術
①行指向の形式: CSV・JSON・Avro
| 形式 | 長所 | 短所 |
|---|---|---|
| CSV | どこでも読める。人が読める | 型がない、区切り文字や改行のエスケープの問題、入れ子を表せない |
| 入れ子と可変の項目を表せる | 項目名を毎行繰り返すため大きい。分析は遅い | |
| スキーマ付きのコンパクトなバイナリ。書き込みが速い。スキーマの進化 (列の追加など) に強い | 列単位の読み取りはできない |
Avro は、 や で流すレコードの形式として、 と組み合わせてよく使われます。書き込みが多い取り込みの段階は行指向、分析の段階は列指向、と使い分けます。
②列指向の形式: Parquet と ORC ⚠️ 頻出
| 特徴 | 効果 |
|---|---|
| 必要な列だけを読む (列の射影) | スキャン量が減る |
| 列ごとの圧縮とエンコーディング | 同じ型・似た値が並ぶため、よく縮む |
| ブロックごとの統計 (最小値・最大値) | 条件に合わないブロックを読み飛ばせる (述語のプッシュダウン) |
| 分割可能 | 大きなファイルを複数のワーカーで並列に読める |
は行グループ (既定 128 MB)、 はストライプ (既定 64 MB) という単位でデータをまとめ、それぞれに統計を持ちます。よく絞り込む列 (例: 日時) でデータを並べておくと、最小値と最大値で読み飛ばせる範囲が広がります。
Parquet と ORC はどちらも列指向で、AWS の分析サービスはどちらも読めます。迷ったら Parquet が最も広く使われます。
⚠️ 頻出: 「 のクエリが遅く、スキャン量の料金が高い。データは CSV」は、Parquet (または ORC) に変換し、圧縮し、パーティションを切ることで解決します。
③圧縮と分割可能性 ⚠️ 頻出
| コーデック | 圧縮率 | 速さ | 分割可能性 (テキストファイルに単体で使った場合) |
|---|---|---|---|
| gzip | 高い | 遅め | 分割できない |
| bzip2 | 非常に高い | 遅い | 分割できる |
| Snappy | 中程度 | 速い | 単体では分割できない (/ の中で使うのが一般的) |
| ZSTD (Zstandard) | 高い | 速い | 単体では分割できない |
| LZO / LZ4 | 低〜中 | 非常に速い | 条件付き |
ポイントは、Parquet や ORC の中で使う圧縮は、行グループやストライプ単位で行われるため、どのコーデックでもファイルは分割可能なままだということです。分割可能性が問題になるのは、CSV や をファイルごと gzip で圧縮した場合です。大きな1つの .csv.gz は1つのワーカーでしか読めず、並列処理が効きません。
| 状況 | 対処 |
|---|---|
| 1つの巨大な .csv.gz | 適度な大きさの複数のファイルに分ける、または Parquet に変換する |
| 列指向で速さを重視 | Parquet + Snappy |
| 列指向で圧縮率も重視 | Parquet + ZSTD (または gzip) |
はスキャンしたバイト数 (圧縮後) で課金されるため、圧縮するだけでも料金が下がります。Athena が書き込むときの既定の圧縮は、Hive 形式の Parquet とテキストでは GZIP、ORC では ZLIB、 テーブルでは ZSTD です。Athena は ZIP 形式を読めず、CSV や JSON の圧縮の種類はファイルの拡張子 (小文字の .gz など) で判断します。
④形式を変換する方法 ⚠️ 頻出
| 方法 | 向くケース |
|---|---|
| ジョブ | 定期的なバッチの変換。結合やクレンジングと同時に で書き出す。partitionKeys でパーティションも作る |
| の形式変換 | ストリーミングの を、届いたそばから Parquet/ にして へ。スキーマは Glue Data Catalog。CSV は で JSON にしてから |
| の / INSERT INTO | 既に S3 にある CSV のテーブルから、 だけで Parquet のテーブルを作る。パーティションとも指定できる |
| () | 非常に大量のデータ、既存の Spark のコード |
| コードを書かずに、レシピで整形して Parquet などで出力 | |
| の | Redshift のデータを Parquet で S3 へ書き出す |
| の S3 ターゲット | データベースから移すときに Parquet で書く |
-- Athena の CTAS で CSV のテーブルから Parquet のテーブルを作る例
CREATE TABLE sales_parquet
WITH (format = 'PARQUET', write_compression = 'SNAPPY',
external_location = 's3://bucket/curated/sales/',
partitioned_by = ARRAY['dt'])
AS SELECT order_id, amount, customer_id, dt FROM sales_csv;
⚠️ 頻出: 「一度だけ、既存の S3 の CSV を Parquet に変換したい。インフラは用意したくない」は Athena の CTAS が手軽です。「毎日届く CSV を変換し続ける」は Glue ジョブ、「ストリームの JSON を変換して保存」は Firehose の形式変換です。
⑤形式とスキーマの扱い
| 課題 | 考え方 |
|---|---|
| 列の追加 | 、、 は列の追加に対応しやすい。 のでカタログを更新する |
| 列の順序や型の変更 | 形式によって扱いが異なる。 などのテーブル形式ではスキーマの進化を安全に行える |
| 入れ子の | Parquet の構造体 (struct) で保持するか、Glue の Relationalize で平らにする |
| 型の不一致 (文字列と数値) | 変換時に型をそろえる (Glue の ResolveChoice、ApplyMapping) |
試験対策
①判断マトリクス
| 問題文のキーワード | 選ぶ形式・方法 |
|---|---|
| のスキャン量とコストを減らす | / + 圧縮 + パーティション |
| 少数の列だけを読む分析が多い | 列指向 (Parquet) |
| ストリーミングで行単位に書く、スキーマを進化させる | (+ ) |
| 大きな .csv.gz の処理が並列にならない | 分割する、または Parquet に変換 |
| 速さ重視の圧縮 | Snappy |
| 既存の の CSV を一度だけ Parquet に、インフラ不要 | Athena の |
| 毎日届く CSV を Parquet に変換 | ジョブ |
| ストリームの を Parquet で S3 へ | の形式変換 |
| のデータを Parquet で S3 へ | |
| コードを書かずに整形して出力 |
②よくある誤答
- 分析用のデータを や CSV のまま置き続けること。スキャン量が増えます。
- の中の Snappy 圧縮で、ファイルが分割できなくなると考えること。Parquet は分割可能なままです。
- 列指向の形式を、1件ずつ頻繁に追記する取り込みに使うこと。が増えます。書き込みは行指向やバッファで受け、まとめて変換します。
- の形式変換が CSV をそのまま読めると考えること。入力は JSON です。