UUID(Universally Unique Identifier)は、中央のID発番サーバを使わずに、各所が独立して生成しても実用上ぶつからない一意な識別子です。128 ビットの値を 8-4-4-4-12 の36文字で表記し、分散システムの主キーやログの相関IDなどに広く使われます。本記事では UUID の表記・バージョンの違い・v4 の構造・衝突確率・使いどころを正確に整理します。
1. UUID とは — 128ビットと 8-4-4-4-12 の表記
UUID は 128 ビット(16 バイト)の値です。人が読み書きしやすいよう、16進数 32 桁をハイフンで区切り、8-4-4-4-12 の 5 ブロック・合計 36 文字で表します。
例:550e8400-e29b-41d4-a716-446655440000
- 各文字は 16 進数の 1 桁(4 ビット = 1 ニブル)。
- ハイフンは可読性のための区切りで、データ本体ではありません。
- 標準仕様は RFC 4122、2024 年にこれを更新・拡張した RFC 9562 が後継です(v6/v7/v8 を追加)。
- Microsoft 系では同じ概念を GUID と呼びます(表記は中括弧付きのことがある)。
このうち、特定の位置のニブル/ビットが「バージョン」と「バリアント」を表すために予約されています。残りが実際のデータ(v4 なら乱数)に使われます。
2. UUID のバージョンの種類
UUID には複数のバージョンがあり、何を元に値を作るかが異なります。代表的なものを示します。
| 版 | 生成の元 | 特徴・備考 |
|---|---|---|
| v1 | 時刻 + ノード(MAC アドレス等) | 時刻順だが MAC を埋め込むためプライバシー上の懸念がある |
| v3 | 名前空間 + 名前(MD5) | 同じ入力から常に同じ UUID を生成(決定的) |
| v4 | 乱数 | 最も一般的。122 ビットが乱数。実装が簡単で偏りがない |
| v5 | 名前空間 + 名前(SHA-1) | v3 の SHA-1 版。決定的に生成したいとき向き |
| v7 | 時刻(ミリ秒)+ 乱数 | RFC 9562 で追加。時刻順に単調増加し DB キーに向く |
迷ったら、用途を選ばない一般的な ID には v4、データベースの主キーなど順序性が欲しいなら v7 を選ぶ、と覚えておけば十分です。
3. v4 の構造 — 122ビットの乱数・version・variant
v4 は 128 ビットのうち、固定で予約される一部のビットを除いた 122 ビットがランダムです。予約ビットは次の 2 つです。
- version ニブル:3 ブロック目の先頭 1 文字が常に
4(2 進で0100)。v4 であることを示します。 - variant ビット:4 ブロック目の先頭 1 文字が
8・9・a・bのいずれか(上位 2 ビットが10)。RFC 4122 のバリアントであることを示します。
つまり 36 文字のうち、必ず特定位置に 4 と 8/9/a/b が現れます。例で位置を確認します。
例:f47ac10b-58cc-4372-a567-0e02b2c3d479
- 3 ブロック目
4372の先頭が4→ version = 4。 - 4 ブロック目
a567の先頭がa→ variant = RFC 4122(上位 2 ビット10)。
4 で始まらない UUID は v4 ではありません。version ニブルと variant ビットを 2 ビット・2 ビットで差し引いて、合計 6 ビットが固定、残り 122 ビットが乱数になります。
4. 衝突確率 — 誕生日問題で考える
「乱数なら、いつか同じ値が出るのでは?」という疑問は当然です。これは誕生日問題(同じ誕生日のペアが現れる確率)の枠組みで見積もれます。
v4 の乱数空間は 2 の 122 乗(約 5.3×1036)通りです。誕生日問題の近似では、おおよそ生成数 n が空間の平方根、すなわち 2 の 61 乗(約 2.3×1018、約 10 京)個に達したあたりで衝突が現実的な確率になり始めます。
- 言い換えると、毎秒 10 億個の UUID を生成し続けても、衝突が現実味を帯びるまでに数十年〜それ以上の桁の時間がかかります。
- 通常のアプリケーションが扱う ID 数(数百万〜数十億)では、衝突確率は宝くじの比ではないほど小さく、実用上は無視できます。
Math.random() で作らない。JavaScript の Math.random() は暗号用途を想定しておらず、予測可能で偏りも生じ得ます。ブラウザでは crypto.randomUUID()、それが使えない環境では crypto.getRandomValues()、Node.js では crypto モジュールを使ってください。
5. 使いどころ — 分散システム・相関ID・ファイル名
UUID の強みは「中央集権の発番なしに、独立して一意な値を作れる」ことです。具体的な使いどころを挙げます。
- 分散システムの主キー:複数ノードやクライアント側で ID を先に決められるため、サーバ往復を待たずにレコードを作れます。
- 相関ID(トレースID):1 リクエストに UUID を割り当て、マイクロサービス間のログを横断的に追跡します。
- ファイル名・オブジェクトキー:アップロードファイル名の衝突回避に便利。ただし推測されにくいだけで、秘密の値ではない点に注意。
- API キー的な用途は慎重に:UUID は識別子であって認証情報ではありません。アクセストークンには十分なエントロピーを持つ専用のランダム値を使うべきで、UUID を権限の根拠にするのは避けます。
6. v4 と v7 の比較 — インデックス局所性
データベースの主キーに UUID を使う場合、v4 と v7 の違いが性能に効いてきます。v4 は完全にランダムなため挿入位置が毎回バラバラで、B-Tree インデックスのページがあちこちで更新され(断片化・キャッシュ効率の低下)ます。v7 は先頭がミリ秒タイムスタンプで時刻順に単調増加するため、新しい行がインデックスの末尾付近にまとまり、局所性が高いのが利点です。
| 観点 | v4(乱数) | v7(時刻 + 乱数) |
|---|---|---|
| 並び順 | 不規則(ランダム) | 生成順に単調増加 |
| インデックス局所性 | 低い(挿入が分散) | 高い(末尾付近に集中) |
| 生成時刻の漏えい | しない | 先頭から推測できる |
| 主な用途 | 汎用の一意識別子 | DB 主キー・時系列キー |
| 標準 | RFC 4122 / 9562 | RFC 9562 |
順序が外部に見えても問題なく、挿入性能を優先したいなら v7、生成時刻すら隠したい・とにかく一様にばらけてほしいなら v4、と用途で選び分けます。
Free Tool UUID Generator で実際に作る ブラウザ内で安全な乱数を使って UUID を生成し、コピーできます。version/variant の位置を含む正しい形式で出力します。よくある質問(FAQ)
UUID v4 は本当に重複しないのですか?
絶対に重複しないという保証はありませんが、v4 は 122 ビットの乱数を持つため、実用上は衝突をほぼ無視できます。誕生日問題で考えても、衝突が現実的な確率で起き始めるには 2 の 61 乗(約 10 京)個ものUUIDを生成する必要があり、通常のシステムでは到達しません。前提として、暗号論的に安全な乱数(CSPRNG)で生成することが重要です。
v4 と v7 はどちらを使うべきですか?
用途によります。一般的な一意識別子としては乱数ベースの v4 が無難です。一方、データベースの主キーのように生成順に並んでいてほしい場合は、先頭にミリ秒タイムスタンプを置く v7 が向いています。v7 は時刻順に単調増加するため B-Tree インデックスの局所性が高く、挿入性能やページ分割の面で有利です。
UUID は安全な乱数で作られていますか?
実装に依存します。v4 の品質は乱数源の品質に直結するため、必ず暗号論的に安全な乱数生成器(CSPRNG)を使ってください。ブラウザなら crypto.randomUUID() や crypto.getRandomValues()、Node.js なら crypto モジュールが該当します。Math.random() は予測可能で暗号用途に適さないため、UUID の生成に使ってはいけません。