0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

データエンジニアなら知っておきたい「データ形式と圧縮」の基本まとめ

0
Posted at

はじめに

データエンジニアリングの現場では、毎日膨大な量のデータを動かします。
その際、データの「持ち方(形式)」や「詰め方(圧縮)」を一つ変えるだけで、次のような劇的な変化が起こります。

  • コストの削減: ストレージ料金や転送費用が 1/10 以下になることも珍しくありません。
  • 処理の高速化: 数時間かかっていた集計処理が、数分で終わるようになります。
  • システムの安定: データの「壊れにくさ(スキーマ管理)」が向上し、予期せぬエラーを防げます。

データ基盤に携わっていく中で、データ形式や圧縮技術を
理解しておくことはもはや必須の知識になっています。

この記事では用途に合わせて最適な技術を選べるようになるための
第一歩として、基本を押さえていきましょう!

押さえておきたい前提知識

各フォーマットを見ていく前に、前提となる4つの基本概念について整理しておきましょう!

1. シリアライズとは?

プログラムで扱っているデータを保存しやすい形式に変換することです。
(例えば、JSONやYAML、バイナリなど)

プログラムが動いている間、データはメモリの中で
「オブジェクト」や「構造体」といった複雑な形で存在しています。

プログラム内で処理している間は問題ないのですが、
保存したい時に、次の壁にぶつかります。

  • ハードディスクには「バイト列(0と1の並び)」しか保存できない
  • ネットワーク上でやり取りする際、データを一列に並べる必要がある

これらを解決するために、
メモリ上のデータをバイト列に変換するのが「シリアライズ」です!

逆に、保存されたファイルからデータを読み込み、
元のメモリ上の状態に復元することが「デシリアライズ」です!

2. 行ベース vs 列ベース

データの並べ方の違いです。(SSDやHDDなど物理的にデータをどのように置くか)
パフォーマンスに直結するので、きちんと理解しておきましょう!

行ベース

「1行(1レコード)」をひとつの塊としてメモリやディスクに並べる方式です。

  • 特徴
    • データの追加(挿入)が速い: 新しいデータが来たら、一番後ろに1件分を追加するだけで済む
    • 1件の詳細を見るのが得意: 「IDが100番の人の名前、住所、電話番号をすべて表示する」といった処理では、1箇所を見れば必要な情報がすべて揃う
  • 主な用途
    • OLTP(オンライン事務処理): 銀行の振り込み、ECサイトの注文、SNSの投稿など、頻繁にデータの追加や更新が発生するシステム
    • 代表的なDB: MySQL, PostgreSQL, Oracle など。

列ベース

「同じカラム(列)」のデータを一箇所にまとめて並べる方式です。
カラム指向のデータベースなんて呼ばれ方もあります。

  • 特徴
    • 集計処理が高速: 「100万件のデータの『売上』だけを合計する」場合、売上のデータだけを一気に読み込めるため、余計なデータ(名前や住所など)を読み込む必要がなくなる
    • データ圧縮効率が高い: 同じ列には「日付」や「数値」など似たデータが並ぶため、圧縮が効きやすく、ストレージ容量を節約できる
  • 主な用途
    • OLAP(オンライン分析処理): 過去1年間の売上分析、ユーザー行動ログの集計など、巨大なデータから傾向を読み取るシステム
    • 代表的なDB: Amazon Redshift, Google BigQuery, Snowflake, Apache Parquet(ファイル形式) など

3. スキーマあり vs スキーマなし

データの中に「どんな名前の項目があり、それは数値なのか文字なのか」
という定義(スキーマ)が含まれているかどうかです。

  • スキーマあり: データの型が保証されるため、壊れにくく、読み込み側での処理がスムーズ
  • スキーマなし: どんなデータも柔軟に入れられるが、読み込む時に型の判定が必要

4. テキスト形式 vs バイナリ形式

人間が中身を読めるかどうかの違いです。

  • テキスト形式(JSON, CSVなど): メモ帳で開いて中身を確認できる。デバッグが楽だが、ファイルサイズは大きくなりがち
  • バイナリ形式(Parquet, Avroなど): 人間には読めない。その分、コンピュータが高速に処理でき、サイズも非常にコンパクト

データ形式:行ベース(Row-oriented)

「1レコード(1行)」をひとかたまりとして保存する形式です。
データの追加(書き込み)が速いため、ログの収集やWebサービスの裏側でよく使われます。

具体的にどんな形式があるか見ていきます!

CSV (Comma-Separated Values)

最も古くからある、カンマ区切りのテキスト形式です。

  • 特徴: 汎用性が非常に高く、Excelなどで直接開ける
  • メリット: 実装が簡単で、人間が中身をパッと確認できる
  • デメリット: 「データ型(数値か文字列か)」の定義がない。また、複雑な階層構造(ネスト)を表現するのが苦手

→ データパイプラインで使うのはできるだけ避けたい。
(エラーの原因になったり、性能が低い。)

XML (Extensible Markup Language)

タグを使って構造を表現する形式です。

  • 特徴: 非常に厳密な構造を持たせることができる
  • 現状: データエンジニアリングの文脈では、タグによるデータの肥大化やパース(解析)の重さから、JSONやAvroに取って代わられていることが多い。古いシステムとの連携で見かける程度

JSON (JavaScript Object Notation)

Webの世界で最も普及している、キーと値のペアで書く形式です。

  • 特徴: テキスト形式でありながら、階層構造(ネスト)を自由に作れる
  • メリット: スキーマを事前に定義しなくても柔軟にデータを追加できる
  • デメリット: 全てのレコードに「キー名」を書き込むため、データ量が増えるとファイルサイズが無駄に大きくなる

BigQuery, Snowflakeなどのデータベースでネイティブにサポートされており
アプリ、API、データベースシステム間のデータ交換の主要な選択肢である。

ただ、パイプラインステージ間やデータ提供を行うときは列ベースの形式の方が性能が良い。

Avro (Apache Avro)

大規模データ処理で好まれる、バイナリ形式のフォーマットです。

  • 特徴: 「スキーマ(定義ファイル)」と「データ本体」をセットで扱う
  • メリット:
    • バイナリなのでJSONより遥かに軽量で高速
    • スキーマエボリューション(後からカラムを増やしても、古いデータと新しいデータを共存させやすい機能)が強力
  • 主な用途: Kafka(リアルタイム配信)や、データレイクへの一時保存

→ 大量にデータを処理するパイプラインを設計するならJSONよりAvroが有力な選択肢になる。

JSONとの違いを整理するために、次の表で確認してみましょう!

比較項目 Apache Avro JSON
データ形式 バイナリ(0と1の羅列) テキスト(人間が読める文字)
可読性 低い(専用ツールがないと読めない) 非常に高い(エディタでそのまま読める)
データサイズ 非常に小さい(バイナリ形式で、毎回キー名を繰り返さないため) 大きい(毎回キー名を含めるため冗長)
処理速度 極めて高速(パースが不要) 低速(文字列の解析にCPU負荷がかかる)
スキーマ(定義) 必須(型や構造を厳密に定義する) 任意(スキーマレスで自由度が高い)
変更への強さ 最強(スキーマエボリューション機能) 弱い(手動でのエラーハンドリングが必要)
主な用途 Kafka, 大規模データパイプライン Web API, 設定ファイル, フロントエンド連携
学習コスト やや高い(定義ファイルの作成が必要) 極めて低い

列ベース(Column-oriented)

同じ項目(カラム)のデータをまとめて保存する形式です。

データ分析の世界では、特定の列だけを合計する・検索するという処理が多いため、この形式がメインとなります。

Parquet (Apache Parquet)

データ分析において、現在もっとも普及しているデファクトスタンダードな形式です。

  • 特徴: 大規模データの保存に最適化されたバイナリ形式。読み取りに強く、書き込みに弱い
  • メリット:
    • 列の読み飛ばし: 100列あるうちの「売上」列だけを読み込む、といった処理が効率的(I/Oを削減できる)
    • 高い圧縮率: 同じ型のデータが並ぶため、非常に効率よく圧縮できる
  • 主な用途: AWS Athena, Google BigQuery, Snowflake など、多くのクラウドDWHや分析基盤での標準

ただ、列ベースの形式は細かいデータの更新が苦手という
弱点もあるので理解しておきましょう!

例えば、ある行の名前を更新したいときその行が含まれるファイル全体を一度解凍し、
中身を書き換えて再度圧縮、新しいファイルに書き出す必要があります。

他にもメタデータの更新の必要があり、データの更新のオーバーヘッドが大きくなっています。

実際は、この課題に対して次の対処法を取ります。

  • バッチ処理
    • 1行ずつ更新せず、1日分や1時間分のデータをまとめて一気にParquet化する
  • パーティショニング
    • データを「日付」などでフォルダ分けし、更新が必要な特定の日付のファイルだけを書き換えるように範囲を絞る
  • テーブルフォーマットの活用
    • Apache IcebergやDelta Lakeといった技術を使い、裏側で「差分(Delta)」だけを別ファイルに持っておき、読み取り時に合体させる仕組みを導入する

Parquetは非常に性能が高く、デファクトスタンダードではありますが、
苦手なこともあるのは知っておいて損はないと思います!

ORC (Apache ORC)

Parquetと非常によく似た性質を持つ、列指向のバイナリ形式です。

  • 特徴: もともとはApache Hive(Hadoop上でSQLを動かす仕組み)向けに最適化されたもの
  • 現状: Parquetほど汎用的ではありませんが、特定のHadoop環境下ではParquet以上の圧縮率や読み込み速度を発揮することがある

Arrow (Apache Arrow)

ディスクに保存するための形式ではなく、メモリ上でデータを保持するための列指向形式です。

  • 特徴: 異なるシステム間(例えばPythonからJavaへ)でデータを渡す際、変換(シリアライズ)の手間をゼロにすることを目指している
  • メリット: データのコピーが発生しないため、メモリ内での計算や転送が極めて高速
  • 主な用途: PandasやSpark、Dremioなど、高速な計算が求められるツールの内部基盤

例えば、裏側はJavaで動いているSparkが、計算はPythonのライブラリを使いたい場合を考えます。

以前はデータの受け渡しのために、データを(一度テキストや他のバイナリ形式へ)シリアライズする必要がありました。
しかし、Arrow形式を使うことでメモリ上でデータをやり取りできるので高速な処理が可能になります!
(シリアライズはデータのコピーや変換処理でCPU時間を多く消費する)

Parquetはディスク上の「保存規格」ですが、Arrowはメモリ上の「共通規格」というイメージです。

ハイブリッドシリアライズ(テーブルフォーマット)

これまでのParquetやAvroは「1つのファイル」の中身をどう並べるかという技術でした。
しかし、大量のParquetファイルが集まると「データの更新」や「古いデータの削除」が難しくなります。

それを解決するのが、複数のファイルを束ねて
一つの巨大な「テーブル」として管理する技術です。

これまでのファイル形式(Parquet, Avro)はデータの「並び方」を決めていました。
このテーブルフォーマットはデータの「管理方法(更新や履歴)」を決めます。

Apache Hudi

元々はUberで開発された、「ストリーミングデータ」の取り込みに強いフォーマットです。

  • 特徴: Parquetのような列指向ファイルに対して、データの追加(Insert)だけでなく、更新(Update)や削除(Delete)を効率的に行える
  • メリット: 「Hadoop Upserts Deletes and Incrementals」の略称通り、データの差分だけを高速に処理するのが得意
  • 主な用途: リアルタイムに近い頻度でデータが更新されるデータレイクの構築

Apache Iceberg

元々はNetflixで開発された、巨大なデータセットを安全かつ高速に扱うためのオープンなテーブル形式です。

  • 特徴: データの「スナップショット(ある時点の状態)」を管理しているため、過去のデータに遡ってクエリを投げる(タイムトラベル)ことが可能
  • メリット: スキーマの変更(カラムの追加や名前変更)が非常に安全に行え、何万ものファイルがあっても高速に検索できる
  • 主な用途: AWS S3などのオブジェクトストレージ上に、数ペタバイト級のデータ基盤を構築する場合

列ベースで難しかった、データ更新の手間を解消してくれます。
(トランザクション性の追加)

圧縮技術

シリアライズ形式が決まったら、次は「どう圧縮するか」を選びます。

圧縮の目的はストレージ容量の節約ネットワーク転送量の削減ですが、
圧縮・解凍にはCPU負荷がかかるため、「圧縮率」と「処理速度」のトレードオフで選びます。

圧縮の仕組みについて軽く押さえておきましょう!

圧縮とはデータの中にある冗長性や繰り返しのパターンを探し、
より短いコードに置き換える(エンコードする)」作業です。

例えば、「AAAAA」というデータを「Aが5個」と表現するだけで、情報量を減らすことができます。

可逆圧縮(Lossless)と非可逆圧縮(Lossy)

圧縮には大きく分けて2つの種類がありますが、
データエンジニアリングの世界では可逆圧縮が使われます。

  • 非可逆圧縮(Lossy)

    • 画像、音声、動画などで使われます。
    • 人間には気づかない程度の細かいデータを削ることで劇的にサイズを落としますが、元のデータには完全には戻せません。
  • 可逆圧縮(Lossless)

    • データエンジニアリングで使われるのはこちらです。
    • 1ビットも欠損させることなく、元のデータを完全に復元できます。
    • 数値や文字列を扱う構造化データでは、1つでも値が変わると計算結果やロジックが壊れてしまうため、必ず可逆圧縮を選びます。

代表的なフォーマット

  • Gzip

    • 特徴: 最も一般的で、圧縮率が非常に高い
    • メリット: どこでも使えて、ファイルをしっかり小さくできる
    • デメリット: CPU負荷が高く、処理が遅め。また、ファイルを分割して並列処理(Splittable)できないため、大規模分散処理には不向き
  • Snappy

    • 特徴: Googleが開発した、「速さ」重視の圧縮方式。
    • メリット: 圧縮率はそこそこだが、とにかく高速でCPU負荷が低い。Parquetとの相性が抜群で、分析基盤のデフォルト設定としてよく使われる。
    • デメリット: Gzipほどは小さくならない。
  • Zstandard (Zstd)

    • 特徴: Meta(旧Facebook)が開発した、次世代の標準。
    • メリット: 圧縮率と速度のバランスが非常に良く、設定次第でGzip並みの圧縮やSnappy並みの高速化も可能。
    • デメリット: 非常に古いシステムだと対応していない場合がある。

おわりに

データ形式や圧縮の選定は、地味に見えてシステムのパフォーマンスとコストに
直結するので、はじめに押さえておきたい概念です。

最初からすべてを完璧に使い分けるのは難しいですが、**なぜこの形式が選ばれているのか?**という背景(トレードオフ)を理解しておくだけで、設計の質は格段に上がると思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?