UUIDガイド:v4とv7の違い、データベースの主キーにUUIDを使うときのポイント
550e8400-e29b-41d4-a716-446655440000 のような文字列は、注文、ファイル、APIリクエストなどあらゆる場所で識別子として使われています。UUIDがどのように生成されるのか、どのバージョンを選ぶべきかを学びましょう。
UUIDとは
UUID(Universally Unique Identifier)は128ビットの識別子で、中央のサーバーに問い合わせなくても、誰もが重複しないIDを作れるようにするものです。MicrosoftではGUIDと呼ばれます。現在の標準は2024年に公開されたRFC 9562です。
16進数32桁をハイフンで 8-4-4-4-12 のグループに区切り、合計36文字で表記します。3つ目のグループの先頭の数字がバージョンを表し、xxxxxxxx-xxxx-4xxx-... ならv4、7xxx ならv7です。
バージョンの早見表
現在は、一般用途にはv4、データベースの主キーのように並び順や挿入性能が重要な場合にはv7を選ぶのが一般的です。
- v1:タイムスタンプとマシンのMACアドレスを組み合わせる。時間順に並ぶが、ハードウェア情報が漏れるおそれがある。
- v3とv5:名前空間と名前をハッシュするため、同じ入力からは常に同じUUIDが得られる(v3はMD5、v5はSHA-1)。
- v4:122ビットのランダム値。最も広く使われ、実装も最も簡単。
- v7:48ビットのミリ秒単位Unixタイムスタンプの後にランダムビットが続く。作成順に並ぶ。
UUIDは本当に衝突しないのか
v4 UUIDのランダム部分は122ビットで、約5.3 × 10^36 通りの値があります。誕生日問題で計算すると、重複が1つ起きる確率が50%になるには約2.7 × 10^18 個のUUIDが必要です。毎秒10億個を85年間作り続ける量で、実際には衝突は起きません。
ただし、これは乱数が本当にランダムな場合に限ります。乱数生成器の状態が同じまま仮想マシンを複製した場合や、予測可能な乱数関数を使った自作実装で重複が報告されています。プラットフォーム標準のUUID関数を使いましょう。
主キーとしてのUUID
UUIDのキーは複数のサーバーで同時に生成でき、レコード数も明かしません。自動採番の整数だと、/orders/1052 のようなURLから競合他社に注文数を推測されてしまいます。
代償はサイズと順序です。UUIDは16バイトで、8バイト整数の2倍あり、36文字の文字列で保存するとさらに大きくなります。v4は完全にランダムなので、新しい行がB-treeインデックスのあちこちに挿入され、ページ分割が頻発して書き込みが遅くなります。v7は時間とともに増加するため、この問題をほぼ避けられます。
- PostgreSQL:ネイティブの uuid 型(16バイト)を使う。
- MySQL:BINARY(16) で保存する。8.0以降は UUID_TO_BIN が使える。
- SQL Server:uniqueidentifier 型を使う。
UUIDを秘密の値に使うべきでない場合
UUIDは一意な名前として設計されたもので、推測できない秘密の値ではありません。v1とv7にはタイムスタンプが含まれるため、一部のビットは予測可能です。パスワード再設定トークンやAPIシークレットのようにセキュリティが重要な値は、十分な量の暗号学的に安全なランダムバイトから生成すべきです。
AIBIZAPのUUID生成ツールで必要な数だけUUIDを作り、秘密の値にはクライアント認証情報生成ツールを使いましょう。JSONのサンプルからテーブルを設計するなら、JSON DDL生成ツールも合わせて使うと便利です。