UUIDとは何か

UUID(Universally Unique Identifier) は、コンピューターシステム上で情報を識別するために使われる128ビットのラベルです。RFC 4122(および2024年のRFC 9562)で標準化されており、通常は次のような正規形式で表記されます。

UUID 完全ガイド:バージョンの違い・使い分け・v4 と v7 の選択

550e8400-e29b-41d4-a716-446655440000

8桁、4桁、4桁、4桁、12桁の16進数をハイフンで区切った、合計36文字(ハイフン4つを含む)の文字列です。

UUIDの根本的な価値は、中央のID管理者と調整することなく、どのマシンでもいつでも生成でき、過去に生成されたどのUUIDとも衝突する確率が天文学的に低いという点にあります。これが、中央集権的なID発行ができない分散システムでUUIDが重宝される理由です。

全バージョン早見表

UUID仕様には複数のバージョンが定義されており、それぞれ生成方式が異なります。

バージョン生成方式ソート可能使いどころ
v1MACアドレス+タイムスタンプ部分的レガシーシステム、監査ログ
v3名前空間+名前のMD5ハッシュ不可既知の入力から決定的なID(旧式)
v4ランダム不可汎用、セッションID
v5名前空間+名前のSHA-1ハッシュ不可既知の入力から決定的なID
v6タイムスタンプ+ランダム(v1の再配置)可能v1の順序付き代替
v7UNIXミリ秒+ランダム可能DB主キー(推奨)
v8カスタムレイアウト場合によるアプリ固有の形式

Version 4:定番のランダム

UUID v4は単純に122ビットの暗号学的乱数です(残り6ビットはバージョンとバリアントを示します)。世界で最も多く生成されているUUIDです。

// ブラウザ / Node.js(標準搭載、ライブラリ不要)
const id = crypto.randomUUID(); // "f47ac10b-58cc-4372-a567-0e02b2c3d479"
# Python
import uuid
print(uuid.uuid4())  # 3d6f4890-4f40-4d09-aa11-3efb...
// Go
import "github.com/google/uuid"
id := uuid.New()

衝突確率: 毎秒10億個のv4 UUIDを86年間生成し続けても、1回でも衝突する確率はおよそ50%です。実用上、衝突は事実上起こり得ません。

欠点: v4はランダムなのでソートできません。ランダムなUUIDを主キーとしてB-treeインデックスに挿入すると、時間とともにインデックスが断片化し、大規模環境では書き込み性能が低下します。

Version 7:現代の標準

UUID v7はRFC 9562(2024年5月)で標準化されました。最上位ビットにUNIXミリ秒タイムスタンプを置き、その後にランダムデータが続きます。

タイムスタンプが上位にあるため、v7 UUIDは 生成時刻順に辞書順ソート可能 です。連続して生成された2つのUUIDは、文字列比較でその順序にソートされます。これはまさにデータベースのインデックスが求める性質です。

// uuidv7 パッケージを使用
import { uuidv7 } from 'uuidv7';

const id1 = uuidv7(); // "018e1f27-42a0-7000-8000-..."
const id2 = uuidv7(); // "018e1f27-42a1-7000-..."
// id1 < id2(文字列比較で正しい順序になる)
// Go(google/uuid v1.6.0+)
id, err := uuid.NewV7()

Version 1:MACアドレス+タイムスタンプ

UUID v1は生成マシンのMACアドレスと100ナノ秒単位のタイムスタンプをエンコードします。マシンの識別子と時刻の組み合わせが一意になるため、衝突リスクは極めて低いです。

欠点として、MACアドレスは個体を識別できる情報です。Webアプリでv1を生成すると、サーバーのハードウェア情報をうっかり露出してしまう可能性があるため、新規システムでは敬遠されています。

Version 3 / Version 5:決定的なUUID

v3とv5はどちらも、名前空間 UUIDと 名前 文字列からハッシュ関数(v3はMD5、v5はSHA-1)を使ってUUIDを生成します。同じ入力からは常に同じUUIDが得られます。外部データから安定した識別子を作るのに便利です。可能ならMD5より強いSHA-1を使うv5を選びましょう。

UUID と連番整数IDの比較

データベースの主キーでは、従来は自動採番の整数(SERIALAUTO_INCREMENT)が定番でした。UUIDはこのトレードオフを変えます。

観点自動採番整数UUID v4UUID v7
IDの予測可能性推測可能(列挙できる)予測不能予測不能
インデックス性能優秀(連番)低い(ランダム書き込み)優秀(時刻順)
分散生成中央調整が必要どのノードでも可どのノードでも可
マージ/レプリケーション複雑容易容易
行サイズ4〜8バイト16バイト16バイト
可読性容易困難困難

マイクロサービス、マルチリージョン展開、複数ソースのデータ統合を行う現代のシステムでは、主キーには UUID v7 がデフォルトの最適解 です。

実務上の注意点

データベースでの保存

  • PostgreSQL: ネイティブの UUID 型を使う。36文字の文字列ではなく16バイトで保存される。
  • MySQL/MariaDB: 効率重視なら BINARY(16)、可読性重視なら CHAR(36)UUID_TO_BIN(uuid, true) でソート可能性を保てる。
  • SQLite: BLOB(16) または TEXT(36)

文字列 vs バイナリ保存

UUIDを文字列("f47ac10b-...")で保存すると36バイト、生のバイナリなら16バイトです。数百万行になると、この差はストレージとインデックスサイズの両方で効いてきます。

試してみる

「UUIDってどんな見た目?」「v4を一気に100個作りたい」。そんなときは UUID生成ツール を使ってみてください。ボタンを押すたびに、一瞬で新しいUUIDが生成されます。

よくある質問

UUID v4 は本当にランダムですか?

UUID v4は122ビットのランダムデータを使います(残り6ビットはバージョンとバリアント用に固定)。「本当に」ランダムかどうかは乱数生成器に依存します。現代の多くの環境は暗号学的に安全な疑似乱数生成器(CSPRNG)を使っており、crypto.randomUUID() はシステムのCSPRNGを使うためセキュリティ用途にも適しています。

既存のv4をすべてv7に移行すべき?

いいえ。既存IDの移行は通常、労力に見合いません。v7の利点(ソート可能性、インデックス局所性)は 新規挿入 に対して効きます。既にv4を使っていてインデックス性能が許容範囲なら、そのままにしましょう。新しいテーブルや新システムからv7を使い始めるのが現実的です。

2台のマシンが同じv4を生成することはありますか?

理論上はあり得ますが、実用上はありません。122ビットのランダム性があるため、50%の衝突確率に達するには約2.7×10¹⁸個のUUIDが必要です。世界中のすべてのマシンが毎秒10億個生成しても、85年以上かかります。

nil UUID とは?

nil UUIDはすべてゼロの 00000000-0000-0000-0000-000000000000 です。「UUIDなし」を示すセンチネル値(null に近い)として使われます。

UUIDの形式を検証するには?

簡単な正規表現でチェックできます。

const UUID_REGEX =
  /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;

UUID_REGEX.test('550e8400-e29b-41d4-a716-446655440000'); // true
UUID_REGEX.test('not-a-uuid'); // false