MySQL の JSON 型の使いどころ

MySQL 5.7.8 で導入された JSON 型は、スキーマレスなデータを格納したい場面で威力を発揮します。すべてのデータを正規化してリレーショナルに管理するのが難しいケースで、柔軟な設計を可能にしてくれます。

JSON 型の基本

JSON 型のカラムには、JSON オブジェクトや配列をそのまま格納できます。MySQL はデータをバイナリ形式に変換して保存するため、TEXT 型に JSON 文字列を入れるよりも効率的にアクセスできます。

CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  attributes JSON NOT NULL
);

INSERT INTO products (name, attributes) VALUES 
('ノートPC', '{"brand": "Dell", "ram": 16, "storage": "512GB SSD"}'),
('スマートフォン', '{"brand": "Apple", "color": "black", "5g": true}');

商品ごとに属性が異なるケースでは、属性をすべてカラムとして定義するのが難しいため、JSON 型が有効な選択肢になります。

JSON データへのアクセス

MySQL では -> 演算子や JSON 関数を使って、JSON 内の特定のキーにアクセスできます。

-- -> はキーで値を取得(引用符付き)
SELECT name, attributes->'$.brand' AS brand FROM products;

-- ->> は引用符なしの値を取得
SELECT name, attributes->>'$.brand' AS brand FROM products;

-- WHERE 句でも使える
SELECT * FROM products 
WHERE attributes->>'$.brand' = 'Apple';

-> と ->> の違いは、-> が JSON 型で返す(文字列に引用符が付く)のに対し、->> はテキスト型で返す(引用符なし)点です。条件比較には通常 ->> を使います。

便利な JSON 関数

JSON_EXTRACT / JSON_SET / JSON_REMOVE

値の取得、設定、削除を行う基本関数です。-> は JSON_EXTRACT のショートハンドで、同じ結果を返します。

JSON_CONTAINS / JSON_SEARCH

特定の値が含まれているかを検索します。JSON 配列から特定の要素を持つレコードを探す場合に使います。

JSON_ARRAYAGG / JSON_OBJECTAGG

集約関数で、クエリ結果を JSON 配列やオブジェクトにまとめます。API のレスポンスを MySQL だけで組み立てたい場面で便利です。

-- JSON の値を更新
UPDATE products 
SET attributes = JSON_SET(attributes, '$.ram', 32) 
WHERE id = 1;

-- JSON にキーを追加
UPDATE products 
SET attributes = JSON_SET(attributes, '$.weight', '1.2kg') 
WHERE id = 1;

-- JSON からキーを削除
UPDATE products 
SET attributes = JSON_REMOVE(attributes, '$.weight') 
WHERE id = 1;

JSON カラムのインデックス

JSON 型のカラムに直接インデックスを張ることはできませんが、MySQL 8.0 では仮想生成カラム(Generated Column)を使った間接的なインデックスが可能です。

-- 仮想カラムを生成してインデックスを作成
ALTER TABLE products 
ADD brand VARCHAR(50) GENERATED ALWAYS AS (attributes->>'$.brand') VIRTUAL,
ADD INDEX idx_brand (brand);

-- 通常のカラムと同じようにインデックスが効く
SELECT * FROM products WHERE brand = 'Apple';

この方法なら、JSON の柔軟性を維持しつつ、頻繁に検索するキーには高速なインデックスアクセスを提供できます。

JSON 型を使うべき場面と避けるべき場面

JSON 型が適している場面

商品属性のようにスキーマが不定なデータ、外部 API のレスポンスの保存、設定情報やメタデータの格納、プロトタイプ段階でスキーマが固まっていない場合。

JSON 型を避けるべき場面

頻繁に検索・ソート・集計するデータ、外部キーで参照したいデータ、スキーマが明確で変わらないデータ。これらは通常のカラムで定義すべき。

JSON 型はリレーショナルモデルとドキュメントモデルの「いいとこ取り」を可能にしますが、乱用するとリレーショナルデータベースの強みを失います。「本当にスキーマが不定か」「将来的に正規化すべきではないか」を冷静に判断した上で採用しましょう。