PostgreSQLでは、どのデータ構造で情報を保存するか悩むことが多いよね。データがシンプルなら配列(ARRAY)を使う?それとも文字列ならテキスト(TEXT)カラム?もしくは「キー-バリュー」ペアを保存するならHSTORE?もちろん、JSONやJSONBを使うタイミングも気になるところ。
このページでは、それぞれのメリット・デメリットや使い方の例を紹介しながら、どれを選ぶべきか一緒に考えてみよう!
配列(ARRAY)とJSONB、どっちを使う?
配列(ARRAY)は、同じ型の値が並ぶデータにピッタリ。例えば、学生の成績リストやタグのリストなら配列が最適だよ。
配列の例:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT,
grades INTEGER[] -- 成績の配列
);
INSERT INTO students (name, grades)
VALUES ('アリス', ARRAY[90, 85, 88]),
('ボブ', ARRAY[70, 75, 78]);
一方で、JSONBはもっと複雑でネストした構造に向いてる。例えば、各成績に説明を付けたい場合はJSONBが便利!
JSONBの例:
CREATE TABLE students_json (
id SERIAL PRIMARY KEY,
name TEXT,
grades JSONB -- 成績データのオブジェクト
);
INSERT INTO students_json (name, grades)
VALUES ('アリス', '{"数学": 90, "理科": 85, "英語": 88}'),
('ボブ', '{"数学": 70, "理科": 75, "英語": 78}');
主な違い
| 基準 | 配列(ARRAY) |
JSONB |
|---|---|---|
| 構造 | 同じ型のデータだけ | 複雑でネストしたデータ構造 |
| データアクセス | インデックスでアクセス: grades[1] |
キーでアクセス: grades->'数学' |
| インデックスサポート | 配列全体にGINやBTREEのみ |
キーごとに便利なGINやBTREEインデックス |
| 使いどき | シンプルなリスト(タグ、成績、IDなど) | キーと値を持つ複雑なオブジェクト |
配列とJSONBの変換例
データを配列とJSONBで変換する方法を見てみよう:
配列 → JSONB
SELECT to_jsonb(grades) AS grades_jsonb
FROM students;
-- 結果:
-- [{"90","85","88"}]
JSONB → 配列
SELECT array_agg(value::INTEGER) AS grades_array
FROM jsonb_array_elements_text('["90", "85", "88"]');
-- 結果:
-- {90,85,88}
JSONBとテキストデータ(TEXT)の比較
テキストカラムは、ただの文字列やちょっとした非構造データを保存したいときに最適。例えば、商品名や説明文で文字列検索したいならTEXTがベスト!
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT,
description TEXT
);
INSERT INTO books (title, description)
VALUES ('SQLの基本', 'SQLへの簡潔な入門書'),
('PostgreSQL上級', 'PostgreSQLパフォーマンスの詳細ガイド');
JSONBを使うべきタイミングは?
もし文字列がネストした情報(例えば、説明文の中にカテゴリやタグリストがある場合)になってきたら、JSONBを選ぼう。
CREATE TABLE books_json (
id SERIAL PRIMARY KEY,
info JSONB
);
INSERT INTO books_json (info)
VALUES ('{"title": "SQLの基本", "tags": ["初心者", "データベース"]}'),
('{"title": "PostgreSQL上級", "tags": ["パフォーマンス", "最適化"]}');
主な違い
| 基準 | テキスト(TEXT) |
JSONB |
|---|---|---|
| 構造 | 非構造データ | 構造化・ネストデータ |
| 検索 | 全文検索 | キー・値・ネスト構造で検索 |
| データ変更 | 全置換のみ | 個別キーの変更OK |
| 使いどき | シンプルなテキスト | キー-バリュー形式の複雑なデータ |
JSONBとHSTOREの比較
HSTOREはJSONBの兄貴分みたいなもので、「キー-バリュー」ペアを保存できる。データ構造がシンプル(ネストや配列が不要)なら、HSTOREは軽くて速いよ。
CREATE TABLE products (
id SERIAL PRIMARY KEY,
attributes HSTORE
);
INSERT INTO products (attributes)
VALUES ('"色"=>"赤", "サイズ"=>"M"'),
('"色"=>"青", "サイズ"=>"L"');
なぜJSONBがHSTOREを置き換えたの?
HSTOREは「キー-バリュー」には便利だけど、ネストや配列ができないから、JSONBの方が汎用性が高い。シンプルなオブジェクトから成長したら、JSONBが自然な次のステップだよ。
主な違い
| 基準 | HSTORE | JSONB |
|---|---|---|
| 構造 | 「キー-バリュー」ペア、ネストなし | 本格的なネスト構造 |
| 配列サポート | なし | あり |
| 検索 | キーのみ | キー・値・ネスト構造で検索 |
| 使いどき | シンプルなキー-バリュー | 複雑なデータ構造 |
どのデータ型を選ぶ?
もしあなたが:
- シンプルな構造(リストや同じ型のデータ)なら配列(
ARRAY)を使おう。 - シンプルな文字列や説明文ならテキストカラム(
TEXT)。 - ネストなしの「キー-バリュー」なら
HSTORE。 - ネストオブジェクトや配列、複雑なデータ構造ならJSONBが必要!
フォーマット間の変換例
TEXT → JSONB
SELECT to_jsonb('シンプルなテキスト例') AS jsonb_form;
-- 結果: "シンプルなテキスト例"
JSONB → TEXT
SELECT info::TEXT AS text_form
FROM books_json;
-- 結果: {"title": "SQLの基本", "tags": ["初心者", "データベース"]}
HSTORE → JSONB
SELECT hstore_to_jsonb(attributes) AS jsonb_form
FROM products;
-- 結果: {"色": "赤", "サイズ": "M"}
JSONB → HSTORE
SELECT jsonb_to_hstore('{"色": "赤", "サイズ": "M"}') AS hstore_form;
-- 結果: "色"=>"赤", "サイズ"=>"M"
気をつけるポイント
柔軟性や複雑な構造が必要ならJSONBを選ぼう。でも、もしデータがシンプル(配列、テキスト、「キー-バリュー」)なら、それぞれに合ったデータ型(ARRAY、TEXT、HSTORE)を使うのがベスト!
データ構造を正しく選ぶことで、後々の開発で頭を抱えずに済むし、クエリのパフォーマンスもアップするよ!
GO TO FULL VERSION