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?

【RDB設計】スキーマレスなデータをどう表現するか?EAVとJSONBの2つのアプローチ

0
Posted at

はじめに

Webサービスを開発していると、「事前にテーブルの列(カラム)を定義しきれない」という設計上の課題に直面することがあります。

例えば、あらゆる商材を扱う総合ECサイトを想像してみてください。
「Tシャツ」ならサイズや色、「冷蔵庫」ならドア数や消費電力、「PCパーツ」ならソケット形状など、商品カテゴリによって管理すべきスペックが全く異なります。これらを1つのテーブルにカラムとして追加していくと、数百のカラムができあがり、そのほとんどが NULL で埋まるスパースデータ(疎なデータ)になってしまいます。

このような「スキーマレスなデータ」をRDB上でどう表現するのか。代表的な2つのアプローチであるEAV(Entity-Attribute-Value)パターンと、JSONB(ドキュメントパターン)の構造と特徴を比較します。


アプローチ1:EAV(Entity-Attribute-Value)パターン

EAVは、データを縦持ち(行)に変換して保存するアプローチです。
データを「主体(Entity)」「属性名(Attribute)」「値(Value)」の3つのテーブルに分解して表現します。

スキーマ構造のイメージ

-- 1. Entity (主体となるデータ)
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

-- 2. Attribute (属性の定義マスタ)
CREATE TABLE attributes (
    id SERIAL PRIMARY KEY,
    code VARCHAR(50) UNIQUE NOT NULL -- 例: 'color', 'power_w'
);

-- 3. Value (値の紐付け)
CREATE TABLE eav_values (
    product_id INT REFERENCES products(id),
    attribute_id INT REFERENCES attributes(id),
    value TEXT NOT NULL,
    PRIMARY KEY (product_id, attribute_id)
);

EAVの特徴

EAVの最大の特徴は、「データ構造(メタデータ)そのものをRDB内で管理できる」という点です。

  • メリット:
    • テーブルのスキーマ変更(ALTER TABLE)を一切行わずに、新しい項目を無限に追加できる。
    • 「属性マスタ(attributes)」が存在するため、システムとしてどんな項目が存在するのかを厳格に統制できる。
  • デメリット:
    • どんな型のデータでも value TEXT に格納せざるを得ないため、DBレベルでの数値や日付の制約(バリデーション)が効かない。
    • 「青色で、かつ消費電力が200W以下」といった複数条件で検索する際、条件の数だけ自己結合(JOIN)が必要になり、SQLが複雑化しやすい。

アプローチ2:JSONB(ドキュメントパターン)

JSONBは、データを横持ちにしつつ、カテゴリごとにブレる動的な項目群を1つのJSON型カラムの中に押し込むアプローチです。NoSQLの柔軟性をRDBに取り入れた設計です。

スキーマ構造のイメージ

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    
    -- 動的な項目をすべてJSONとして格納
    dynamic_attributes JSONB NOT NULL DEFAULT '{}'
);

-- JSON内部を高速に検索するためのGINインデックス
CREATE INDEX idx_product_attributes ON products USING GIN (dynamic_attributes);

JSONBの特徴

JSONBの特徴は、「データの柔軟性と、クエリのシンプルさを両立している」という点です。

  • メリット:
    • 1つのレコードとしてデータがまとまっているため、EAVのような複雑なJOINが不要。
    • GINインデックスを活用することで、JSON内の特定のキー(例: {"color": "blue"})での検索を高速に行える。
    • アプリケーション側(GoやTypeScriptなど)の構造体やオブジェクトと直接マッピングしやすく、開発体験(DX)が良い。
  • デメリット:
    • JSON内のキー名や構造が自由すぎるため、表記揺れ(colorColour など)を防ぐ仕組みをアプリケーション側で実装する必要がある。
    • JSON内部の値を取り出して集計(GROUP BY など)を行う際、テキスト抽出と型キャストの処理が毎回発生する。

3. 2つのアプローチの使い分け

RDBでスキーマレスなデータを扱う場合、どちらの手法を選択するかは「誰がスキーマの主導権を握るか」によって決まります。

  • EAVを採用するケース
    エンドユーザー自身が、システムの設定画面から新しい項目を自由に作成・管理するような要件(例:アンケート作成ツールや、ノーコードの業務アプリ構築機能など)。未知の項目に対しても、システムとして強固な統制が必要な場合に向いています。
  • JSONBを採用するケース
    商品のスペック情報や、外部APIから受け取る可変のペイロードなど、項目の多様性を許容しつつも、開発者側(コード側)でデータ構造をある程度担保できる要件。現在のWeb開発においては、パフォーマンスと実装コストの観点からこちらが主流のアプローチとなっています。

要件に合わせて、RDBの表現力を適切に使い分けていきましょう。

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?