UUID vs オートインクリメントID

データベース主キーとしてのUUID vs オートインクリメント整数を比較。パフォーマンス、スケーラビリティ、セキュリティ、移行の複雑さの観点から最適な選択を解説します。

Comparison

詳細な説明

UUIDとオートインクリメント整数のどちらを主キーにするかは、データベース設計で最も議論されるトピックの一つです。アプリケーションのアーキテクチャと規模に応じて、それぞれに明確な利点があります。

オートインクリメントの利点:

  • ストレージが小さい: 4バイト(INT)または8バイト(BIGINT)vs 16バイト(UUID)。インデックスサイズ、JOINパフォーマンス、キャッシュされたインデックスのメモリ使用量に影響します。
  • インデックスの局所性が良い: 連番はB-treeインデックスの末尾に追加されるため、ページ分割が最小限で最適な書き込みパフォーマンスが得られます。
  • 人間が読みやすい: 注文番号#12847は 550e8400-e29b-41d4-a716-446655440000 より伝達しやすいです。
  • 自然な順序付け: IDが暗黙的に作成順序をエンコードします。

UUIDの利点:

  • 分散生成: 複数のサーバーが調整なしに独立してIDを生成でき、単一障害点やシーケンスのボトルネックを排除します。
  • マージが容易: 複数のデータベースからデータを統合する場合(マイクロサービス、マルチテナント、シャーディング)、UUIDは衝突しません。整数IDはリマッピングが必要です。
  • 不透明性によるセキュリティ: 連番IDは情報を漏洩させます(レコード総数、作成レート、列挙攻撃)。UUIDは何も明かしません。
  • クライアントサイド生成: サーバーへのラウンドトリップ前にクライアントがIDを作成でき、楽観的UIアップデートやオフラインファーストアーキテクチャを実現します。

パフォーマンスベンチマーク(PostgreSQL、1000万行テーブル):

                  | BIGINT PK  | UUID v4 PK | UUID v7 PK
INSERT rate       | 45K/s      | 18K/s      | 40K/s
Index size        | 214 MB     | 412 MB     | 412 MB
SELECT by PK      | 0.02ms     | 0.03ms     | 0.03ms
Range scan (1000) | 1.2ms      | 3.8ms      | 1.5ms

UUID v7は時刻順序の性質によりインデックスの局所性が保たれるため、オートインクリメントのINSERTパフォーマンスにほぼ匹敵します。残りの差はキーサイズの違い(16バイト vs 8バイト)によるものです。

ハイブリッドアプローチ: 多くの本番システムでは、UUIDを公開向け識別子として、オートインクリメント整数を内部主キーとして併用します。これにより、APIではUUIDのセキュリティを、JOINやインデックスでは整数のパフォーマンスを得ることができます。

CREATE TABLE orders (
  id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  public_id UUID NOT NULL DEFAULT gen_random_uuid() UNIQUE,
  -- ... other columns
);

推奨事項: 単一データベースのモノリシックアプリケーションには、オートインクリメントがよりシンプルで高速です。分散システム、マイクロサービス、クライアントサイドID生成が必要なアプリケーションにはUUID v7を使用してください。

ユースケース

UUID vs オートインクリメントの判断は、各サービスが独自のデータを所有しつつ参照を共有する必要があるマイクロサービスアーキテクチャの設計時に特に重要です。分散ID生成により調整のオーバーヘッドを回避できます。

試してみる — UUID Generator

フルツールを開く