【実務・中級編】 配列型 (Array Types) – PostgreSQL

「配列型(Array Types)を使いこなして、PostgreSQLのポテンシャルを解放しよう」

やあ。今日はPostgreSQLのちょっと「攻めた」機能、配列型について話をしようか。

RDBMSの設計において「1対多」の関係を作るなら、基本は正規化して別テーブルに切り出すのが鉄則だよな。それは今でも変わらない。でも、現場で開発していると、「わざわざ別テーブルを切るほどじゃないんだけど、かといってJSONで持つのもクエリが面倒だな……」なんてシチュエーション、あるよね。

そんなとき、PostgreSQLの配列型は最高にクールな選択肢になるんだ。今日はその勘所と、実務でハマらないためのコツを伝授するよ。

1. 配列型の基本:型定義は直感的だ

PostgreSQLの配列型は、ほとんどの型に対して後ろに `[]` をつけるだけで定義できる。

CREATE TABLE user_profiles (
id serial PRIMARY KEY,
username text,
tags text[], — 文字列の配列
login_history int[] — 整数の配列
);

データの挿入も、おなじみの配列リテラルを使えばいい。

INSERT INTO user_profiles (username, tags)
VALUES (‘satoshix’, ‘{“postgresql”, “ruby”, “rust”}’);

これだけで、`tags` カラムの中に3つの要素が綺麗に収まる。シンプルだろう?

2. 実務で光る!配列操作の魔法

配列型が本当に威力を発揮するのは、その「操作演算子」の豊富さだ。これを知っているかどうかで、クエリの書きやすさが劇的に変わる。

特定の要素を含むかチェックする (`@>`)

「このタグを持っているユーザーを検索したい」という要件は頻出だ。ここで `LIKE` を使うなんて野暮なことはせず、包含演算子 `@>` を使おう。

— “postgresql” タグを持つユーザーを探す
SELECT FROM user_profiles WHERE tags @> ‘{“postgresql”}’;

これ、インデックスさえ貼っておけば爆速なんだ。後述するけど、ここが配列型の強みだよ。

配列同士の重なりを調べる (`&&`)

「興味関心が1つでも被っているユーザー」を探すようなケースだ。

— 検索条件のいずれかのタグを持つユーザー
SELECT FROM user_profiles WHERE tags && ‘{“python”, “rust”}’;

要素を追加・削除する (`array_append` や `array_remove`)

アプリ側で配列を操作して全件アップデートするよりも、DB側で完結させたいケースも多いよね。

— タグを追加
UPDATE user_profiles
SET tags = array_append(tags, ‘go’)
WHERE id = 1;

3. 多次元配列という名の「沼」と「武器」

実はPostgreSQLは多次元配列も扱える。`text[][]` のように定義するんだ。
ただ、正直に言うと、実務で多次元配列を多用するのはあまりおすすめしない。データ構造が複雑になりすぎて、後からメンテする人間が泣くことになるからね。

もし「座標データ」や「行列計算」が必要な場合以外は、素直に一次元配列で運用するのが、チーム開発における「平和」の秘訣だ。

4. パフォーマンスの要:GINインデックス

ここが一番大事なポイントだ。配列型を使うなら、GIN (Generalized Inverted Index) インデックスを絶対に忘れないでくれ。

普通のB-treeインデックスは「値そのもの」をインデックスするけど、配列の中身を検索対象にするならGINが最適だ。

CREATE INDEX idx_user_tags ON user_profiles USING GIN (tags);

これさえ貼っておけば、何百万件のデータがあっても `@>` 演算子による検索は一瞬で終わる。「配列型は遅い」なんて言う奴がいたら、たいていこのインデックスを忘れているだけさ。

現場の先輩からのアドバイス

最後に、僕が実務で学んだ教訓を2つだけ伝えておく。

1. 「正規化」とのバランスを忘れるな
配列型は便利だけど、配列内の要素に対して「外部キー制約」をかけることはできない。データの整合性が厳密に求められるなら、迷わず別テーブルへ切り出そう。配列型は「属性」や「ログ的要素」に向いている。

2. 要素数はほどほどに
数千個の要素を持つような配列を作ると、メモリを食うしクエリのオーバーヘッドも増える。あくまで「数個〜数十個」の要素を扱うためのものだと割り切るのがスマートだ。

配列型を使いこなすと、PostgreSQLという強力な相棒の、また違った顔が見えてくるはずだよ。ぜひ、次回の設計で検討してみてくれ。

何か詰まったら、いつでも聞きに来るといい。応援しているよ!

コメント

タイトルとURLをコピーしました