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生成により調整のオーバーヘッドを回避できます。