CodeGym /コース /SQL SELF /JSONJSONBの比較:それぞれのフォーマットのメリッ...

JSONJSONBの比較:それぞれのフォーマットのメリット・デメリット

SQL SELF
レベル 33 , レッスン 1
使用可能

JSONとJSONBの主な違いの一つは、データの保存フォーマットだよ。JSONはデータをテキストとして保存するけど、JSONBはバイナリ形式で保存する。つまり:

  • JSONは、渡したデータをそのまま保存する。たとえば、{"title": "PostgreSQL", "tags": ["database", "SQL"]}という文字列を挿入したら、そのまま保存される。
  • JSONBは、まずJSONオブジェクトをパースして、余計なスペースを消して、キーを並べ替えて、構造を最適化してからバイナリ形式で保存する。

この最適化のおかげで、JSONBは特に複雑なフィルタや検索、ソートのクエリでデータ処理が速くなるんだ。

読み書きパフォーマンス

JSONとJSONBは、データの読み書き速度に違いがある:

  • JSONは、保存前にパースしなくていいから書き込みが速い。でも、読み込みや処理は遅くなりがち。なぜなら、PostgreSQLがクエリ実行時に毎回パースし直す必要があるから。
  • JSONBは、保存前にデータを処理するので書き込みは遅め。でも、読み込みやフィルタ、値の抽出はかなり速い。だから分析や検索系の用途にはJSONBがオススメ。

イメージしやすい例:

-- JSONとJSONBのテーブル作成
CREATE TABLE json_example (data JSON);
CREATE TABLE jsonb_example (data JSONB);

-- データ挿入
INSERT INTO json_example VALUES ('{"key": "value", "tags": ["json", "example"]}');
INSERT INTO jsonb_example VALUES ('{"key": "value", "tags": ["jsonb", "example"]}');

-- データのフィルタ
SELECT * FROM json_example WHERE data->'key' = '"value"';  -- 遅い
SELECT * FROM jsonb_example WHERE data->'key' = '"value"'; -- 速い

データのインデックス化

JSONBの最大のメリットの一つはインデックス対応。PostgreSQLはJSONBカラムにGINインデックスを作れる。これで検索やフィルタがめっちゃ速くなる!

インデックス作成例:

-- JSONBカラムのインデックス
CREATE INDEX idx_jsonb_tags ON jsonb_example USING gin (data->'tags');

逆にJSONはインデックス非対応なので、複雑な検索やフィルタには向いてない。

JSONJSONB、どっちを使う?

JSONが向いてるケース:

  • データをそのままの形で保存したい時。
  • JSONデータでフィルタや検索、ソートをあまりしない場合。
  • JSONデータを他のシステムやクライアントにそのまま渡す用途(例:API経由でフロントエンドに返すなど)。

例:

-- 解析せずにJSONを保存
CREATE TABLE api_responses (
    id SERIAL PRIMARY KEY,
    response JSON
);

-- APIから来たデータをそのまま挿入
INSERT INTO api_responses (response)
VALUES ('{"status": "success", "payload": {"id": 123, "name": "John"}}');

JSONBがオススメな場合:

  • JSON内の値でフィルタ、検索、グループ化、ソートをよく使う時。
  • データアクセスのパフォーマンスが書き込み速度より大事な時。
  • JSONデータの操作を速くするためにインデックスを使いたい時。

例:

-- 分析やネストしたオブジェクト操作用にJSONBを保存
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    details JSONB
);

-- データ挿入
INSERT INTO products (details)
VALUES ('{"name": "Laptop", "price": 1200, "tags": ["electronics", "computers"]}');

-- "electronics"タグ付き商品を検索
SELECT * FROM products
WHERE details @> '{"tags": ["electronics"]}';

@>や-->演算子については次のレクチャーで詳しくやるよ :P

JSONJSONBの操作例

JSONカラムとJSONBカラムの2つのテーブルを作ってみよう:

CREATE TABLE json_table (
    id SERIAL PRIMARY KEY,
    data JSON
);

CREATE TABLE jsonb_table (
    id SERIAL PRIMARY KEY,
    data JSONB
);

どちらのテーブルもデータの挿入方法は同じ:

INSERT INTO json_table (data)
VALUES ('{"key": "value", "tags": ["json", "example"]}');

INSERT INTO jsonb_table (data)
VALUES ('{"key": "value", "tags": ["jsonb", "example"]}');

次に、keyvalueのデータを抽出してみる:

-- JSONの場合
SELECT * FROM json_table
WHERE data->>'key' = 'value';

-- JSONBの場合
SELECT * FROM jsonb_table
WHERE data->>'key' = 'value';

データ量が少ないうちはパフォーマンス差はほぼない。でも、何百万行も扱う場合はJSONBが圧倒的に速くなる。特にインデックスを作れば:

CREATE INDEX idx_jsonb_key ON jsonb_table USING gin ((data->>'key'));

ネストしたオブジェクトや配列の操作もJSONBの方が効率的:

-- 配列から値を取り出す
SELECT data->'tags'->>0 AS first_tag 
FROM jsonb_table;

メリット・デメリットまとめ

特徴 JSON JSONB
データ保存 元のテキスト形式で保存 キーを並べ替えてバイナリ形式で保存
書き込みパフォーマンス そのまま保存なので速い 事前パースがあるので遅め
読み込みパフォーマンス クエリ時にパースが必要なので遅い 最適化済みなので速い
インデックス 非対応 対応(GIN、BTREEインデックス)
フィルタ 遅い 速い
操作サポート 限定的 拡張されている

JSONとJSONBの選択は用途次第。単にテキストのままデータを保存したいだけならJSONでOK。でも、カラム内のデータをガンガン操作したり、フィルタや検索、グループ化をしたいなら、JSONBの方がパフォーマンスも使い勝手も良いよ。

複雑なアプリで、JSONデータが「ただの保存場所」じゃなくて分析にも使うなら、JSONBはマジで必須。迷ったらとりあえずJSONBにしとこう。きっと将来「人生最速クエリ」が出せて感謝されるはず!

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION