【実務・中級編】 UUID型 – PostgreSQL

「主キーに何を使うか?」というのは、データベース設計における永遠のテーマですよね。

駆け出しの頃は「とりあえず `SERIAL` か `BIGSERIAL` でいいや」となりがちですが、システムが大きくなって、分散環境での運用や、IDの推測を防ぐ必要が出てくると、そうも言っていられなくなります。

そこで頼りになるのが UUID (Universally Unique Identifier) です。今日は、PostgreSQLでUUIDを賢く使うための勘所を、現場の実践的な視点から解説します。

—

なぜ「連番」から「UUID」に移行するのか

連番(`SERIAL`)には、致命的な弱点が2つあります。

1. 推測が容易: `…/users/123` というURLがあれば、次は `124` だと誰でも分かります。これはセキュリティ的に非常に危険です。
2. マージが困難: 複数のDBサーバーや、オフラインで生成したデータをマージする際、IDの衝突を避けるための調整が地獄になります。

UUIDなら、中央集権的な管理なしに、世界中でほぼ確実に重複しないIDを生成できます。これが分散システムやマイクロサービスにおいて、UUIDが標準的に使われる理由です。

PostgreSQLでのUUID活用術

PostgreSQLでUUIDを使うのは、驚くほど簡単です。`pgcrypto` 拡張(PostgreSQL 13以降は標準機能でOK)を使い、データ型として `uuid` を指定するだけです。

1. テーブル定義の例

まずは、シンプルにUUIDを主キーにするテーブルの定義を見てみましょう。

CREATE TABLE users (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
username text NOT NULL,
created_at timestamptz DEFAULT now()
);

見ての通り、`DEFAULT gen_random_uuid()` を指定するだけで、レコード挿入時に自動的にランダムなIDが割り振られます。アプリケーション側でIDを生成して渡す必要すらありません。

2. パフォーマンスの落とし穴:インデックス問題

ここで一つ、ベテランとしてアドバイスしておきたいことがあります。

UUIDを主キーにすると、インデックス(B-tree)の断片化が起こりやすいんです。`gen_random_uuid()` で生成されるUUID(バージョン4)は完全にランダムなので、インデックスの「新しいノード」がランダムな位置に書き込まれます。これによってページ分割が頻発し、挿入性能がガクンと落ちることがあります。

もし、「IDの生成順序」と「挿入順序」をある程度一致させたいなら、UUID v7 の利用を検討してください。

  • UUID v4: 完全ランダム。セキュリティ重視。
  • UUID v7: タイムスタンプを含む。ソート可能でインデックス効率が良い。

PostgreSQL 17以降であれば `gen_random_uuid()` が賢くなっており、状況によってはv7相当の動作を選択することも可能ですが、そうでなければ拡張ライブラリ(`pg_uuidv7`など)の導入を検討する価値は十分にあります。

現場でよくある「うっかり」

最後に、実務でよく見る失敗をいくつか共有します。

  • 文字列型 (`text` や `varchar`) で保存してしまう:

UUIDは必ず `uuid` 型を使ってください。`text` 型で保存すると、インデックスサイズが倍以上に膨れ上がり、クエリ速度が目に見えて低下します。「見かけは文字でも、内部では128ビットの数値」として扱うのがPostgreSQLの流儀です。

  • クエリの可読性:

IDが `550e8400-e29b-41d4-a716-446655440000` となると、デバッグ時に「これどのユーザーだっけ?」となりがちです。開発環境では、デバッグツールでIDからユーザー名を引けるようにしておくなど、運用でカバーする仕組みを作っておくとチームの生産性が上がります。

—

結び

UUIDは「とりあえず使っておけば安心」な万能ツールではありません。インデックスの特性や、IDとしての性質(ランダムか、ソート可能か)を理解して使い分けることで、初めてデータベースの真価を発揮します。

「何となく `BIGSERIAL`」から卒業して、システムに最適なID設計ができるようになると、設計の自由度がグッと広がりますよ。

もし「UUIDのインデックスサイズをさらに小さくしたい!」なんていうニッチな相談があれば、またいつでも聞いてください。データベースの深いところまで、一緒に掘り下げていきましょう。

コメント

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