メインコンテンツへスキップ

← ブログ一覧へ

UUID vs 連番 ID:データベースの主キーはどちらを選ぶ?

テーブルを作るとき、主キー戦略を選びます —— そしてこの決定は思いのほか影響が大きいものです。最もよくある選択は連番整数UUID の 2 つ。両者の比較と使い分けを見ていきましょう。

連番整数

BIGINT AUTO_INCREMENT(Postgres の SERIAL)のような列は、行が挿入されるたびに 1、2、3… と払い出します。

利点:コンパクト(4〜8 バイト)、人間が読める、自然に順序付き、そしてインデックス局所性が優れている —— 新しい行は B-tree の末尾に追加され、挿入が高速です。

欠点:情報が漏れる(競合が /users/5000 を見れば規模がわかる)、推測可能(認可が甘いと列挙攻撃を許す)、そして分散・シャーディング環境で扱いにくい —— 2 つのノードが協調なしに次の番号を独立して発行できないためです。

UUID

UUID は 550e8400-e29b-41d4-a716-446655440000 のような 128 ビットの識別子です。v4 は乱数なので、どのノードも協調なしに生成でき、衝突リスクは実質ゼロ。データベース往復の前にクライアント側で作ることもできます。UUID ジェネレーターでまとめて生成すると形式がわかります。

利点:協調なしで全世界的に一意、件数が漏れない、推測不可、データベース間でマージ可能。

欠点:大きい(16 バイト、テキストなら 36 文字)、人に優しくない、そして重要なのは —— ランダムな UUIDv4 はインデックス局所性を損なうこと。新しいキーが B-tree のあちこちにランダムに落ちるため、挿入でページ分割が起き、インデックスが断片化して大きなテーブルで書き込みが遅くなります。

中間解:UUIDv7 / ULID

「どこでも一意」と「インデックスに優しい」のどちらかを選ぶ必要はありません。時刻順の ID、すなわち UUIDv7ULID はタイムスタンプの接頭辞を埋め込むため、全世界的に一意でかつほぼ順序付き —— UUID の分散フレンドリーさを保ちつつインデックス局所性を回復します。UUID の利点を書き込みペナルティなしで得たい新規システムでは、これが既定になりつつあります。

選び方

  • 小規模・単一 DB・内部 ID? 連番はシンプルで速い。
  • 公開する ID、または規模を隠したい? UUID(あるいは対外は UUID、内部は整数キーを保持)。
  • 分散・シャーディング・クライアント生成 ID? UUID —— インデックス性能のため理想は UUIDv7/ULID
  • 連番 ID をセキュリティに頼らないこと。キーがどれだけ推測しやすくても、認可は必ず実施しましょう。

ひとことまとめ

連番はシンプルさと生のインデックス性能で勝り、UUID は一意性・プライバシー・分散で勝ります。両取りしたいなら時刻順の UUIDv7/ULID を。

今すぐ識別子が必要?無料の UUID ジェネレーターがブラウザで RFC 4122 v4 ID を生成 —— まとめて生成し、ワンクリックでコピーできます。