配列とJSONBの比較
今日は配列についてもっと深く理解して、さらにJSONBと比べてみて、それぞれの強み・弱みや、実際の課題でどう使い分けるのがベストかを考えてみよう。
配列 vs JSONB:データのミニカメたち vs 箱入りフレキシビリティ
もう知ってると思うけど、PostgreSQLの配列には同じ型の値だけを入れられるんだ。たとえば数字、文字列、日付の配列とか。例:学生の成績リスト、全部数字だよね。
-- 学生とその成績のテーブル
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT,
grades INTEGER[] -- 成績の配列
);
JSONBは配列と違って、データをJSON構造で保存するんだ。JavaScriptのobjectっぽいけど、パースもインデックスも速いのがメリット。JSONBには順序付きリストも、キーと値のobjectも入れられるよ。
-- 学生とそのいろんなデータのテーブル
CREATE TABLE students_details (
id SERIAL PRIMARY KEY,
name TEXT,
details JSONB -- フレキシブルなJSON構造
);
JSONBのデータ例:
{
"grades": [90, 82, 77],
"address": {
"city": "Berlin",
"zip": "352912"
}
}
つまり、配列は値のリストをシンプルに扱うためのもので、JSONBはもっと複雑なデータに対応できるんだ。
配列とJSONBの主な違い
| 特徴 | 配列 | JSONB |
|---|---|---|
| 構造のタイプ | リニアなデータ構造 | 階層的なデータ構造 |
| 要素の型 | 一つのデータ型だけ | いろんなデータ型 |
| 構造のサイズ | 固定(リニア) | フレキシブル、リストやobjectもOK |
| アクセス速度 | 固定データなら速い | 複雑な検索はちょい遅い |
| インデックス | インデックス対応バッチリ | GINタイプのインデックスが必要 |
| 用途 | シンプルなリストや値の配列 | 複雑なデータ:ネストobject/リスト |
じゃあ、実際どう使うのか見てみよう。
配列を使うときは?
たとえば本のデータベースがあって、1冊の本が複数ジャンルに属する場合。ここは配列がピッタリ。
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT,
genres TEXT[] -- ジャンルの配列
);
-- 複数ジャンルの本を挿入する例
INSERT INTO books (title, genres)
VALUES ('1984', ARRAY['Dystopia', 'Political Fiction', 'Science Fiction']);
配列が向いてるのは、
- データがきっちりリストで管理できるとき、
- リストが小さくて同じ型(文字列や数字など)、
- リストを保存・取り出すだけでOK(複雑な操作しない)
配列のメリット
- 同じ型のデータをシンプルに保存できる。
- タグ、カテゴリ、成績みたいな小さいリストに便利。
JSONBを使うときは?
今度は、本についてもっと複雑なデータ(ジャンル、ISBN、評価など)を保存したい場合。配列じゃ無理だから、ここはJSONBの出番!
CREATE TABLE books_details (
id SERIAL PRIMARY KEY,
title TEXT,
details JSONB -- 本の詳細をJSONBで
);
-- 複雑な本情報を挿入する例
INSERT INTO books_details (title, details)
VALUES (
'1984',
'{"genres": ["Dystopia", "Political Fiction", "Science Fiction"],
"isbn": "9780451524935",
"rating": 8.9}'
);
JSONBが向いてるのは、
- 複雑またはバラバラなデータ(数字、文字列、リスト、object)を保存したいとき、
- テーブル構造を変えずにパラメータを追加したいとき、
- ネストしたデータ(住所、特徴、設定など)を保存したいとき。
JSONBのメリット
- 超フレキシブル。テーブル構造を変えずに新しいキーや値を追加できる。
- APIのJSONレスポンスみたいな複雑なデータ保存に最適。
配列とJSONBの選び方
同じ型のリストだけ保存したいなら配列を使おう。 例えば:
-- イベント参加者IDの保存
CREATE TABLE events (
id SERIAL PRIMARY KEY,
participant_ids INTEGER[]
);
データがバラバラ・複雑ならJSONBがベター。 例えば:
-- 住所付きの顧客情報保存
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
info JSONB
);
インデックスの仕組みは配列とJSONBで違うよ。 配列にはGINインデックスがよく使われて、JSONBにはデータ構造によってGINやBTREEが使われる。
パフォーマンス
配列は典型的な検索タスクなら速い。JSONBはちょい遅いけどフレキシビリティが強み。要素(ジャンルやIDなど)を探すだけなら配列の方が速いよ:
-- 配列+GINインデックスの利用
CREATE INDEX idx_genres ON books USING GIN(genres);
-- ジャンルで本をフィルタ
SELECT * FROM books WHERE genres @> ARRAY['Science Fiction'];
データの存在チェック
JSONBはキーでのフィルタがもっと柔軟:
-- "genres"キーの存在チェック
SELECT * FROM books_details WHERE details ? 'genres';
-- リスト内要素の存在チェック
SELECT * FROM books_details WHERE details->'genres' ?| ARRAY['Fantasy', 'Dystopia'];
配列は値を直接探せる:
-- 配列内要素の存在チェック
SELECT * FROM books WHERE genres @> ARRAY['Fantasy'];
構造のフレキシビリティ
データが複雑でネストしてるならJSONBが最強:
{
"genres": ["Fantasy", "Adventure"],
"ratings": {"goodreads": 8.5, "amazon": 4.7}
}
配列だと、こういうのは正規化や追加カラムなしじゃ無理。
結局、配列とJSONBはライバルじゃなくて、用途が違うツールなんだ。データがリストっぽいなら配列。複雑・ネスト・バラバラなデータなら迷わずJSONB。大事なのはパフォーマンスとインデックスも忘れないこと!
GO TO FULL VERSION