はじめに
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内のキー名や構造が自由すぎるため、表記揺れ(
colorとColourなど)を防ぐ仕組みをアプリケーション側で実装する必要がある。 - JSON内部の値を取り出して集計(
GROUP BYなど)を行う際、テキスト抽出と型キャストの処理が毎回発生する。
- JSON内のキー名や構造が自由すぎるため、表記揺れ(
3. 2つのアプローチの使い分け
RDBでスキーマレスなデータを扱う場合、どちらの手法を選択するかは「誰がスキーマの主導権を握るか」によって決まります。
-
EAVを採用するケース
エンドユーザー自身が、システムの設定画面から新しい項目を自由に作成・管理するような要件(例:アンケート作成ツールや、ノーコードの業務アプリ構築機能など)。未知の項目に対しても、システムとして強固な統制が必要な場合に向いています。 -
JSONBを採用するケース
商品のスペック情報や、外部APIから受け取る可変のペイロードなど、項目の多様性を許容しつつも、開発者側(コード側)でデータ構造をある程度担保できる要件。現在のWeb開発においては、パフォーマンスと実装コストの観点からこちらが主流のアプローチとなっています。
要件に合わせて、RDBの表現力を適切に使い分けていきましょう。