ゆるテックノート

UUIDの小ネタ・実務Tips

UUIDを採用するときは、重複しにくさだけでなく、並べ替え方や保存先も考えると判断しやすくなります。基本の構造はUUIDとは?で説明しています。

衝突確率の目安

独立で均一な乱数から作るUUIDv4を想定します。122ビットの候補からn個生成したとき、少なくとも1組が重複する確率は、小さい確率の範囲で p ≈ n(n−1) / (2 × 2^122) です。特定の2個だけが一致する確率とは異なります。

生成件数ごとの計算

生成件数 衝突確率(近似)
10^6 9.4 × 10^-26
10^9 9.4 × 10^-20
10^12 9.4 × 10^-14

重複に備える

  • DBのユニーク制約で重複を検出し、衝突時の再生成・再試行を設計します。制約自体がIDを生成するわけではありません。
  • 乱数の偏りや同じ値の使い回しがあると、この計算は当てはまりません。文字列を途中で切ると候補数も減ります。

時系列性と類似フォーマット

UUIDv7は2024年5月のRFC 9562で標準化されています。ULIDとKSUIDは別形式で、UUIDの入力欄にそのまま渡すことはできません。

サイズと構造

形式 構造 文字列表記
UUIDv4 128ビット(乱数122ビット) 16進数とハイフンで36文字
UUIDv7 128ビット。先頭48ビットがUnix時刻(ミリ秒) 16進数とハイフンで36文字
ULID 128ビット=時刻48+乱数80 Crockford Base32で26文字
KSUID 160ビット=時刻32+乱数128 Base62で27文字

順序と互換性を確認する

  • UUIDv7の残り74ビットは乱数が基本で、実装により一部を細かい時刻やカウンターに使えます。同一ミリ秒内や時計が戻った場合の順序は、ライブラリの仕様を確認します。
  • ULIDも同一ミリ秒内の生成順を常に保証するわけではありません。単調増加モードは別途確認します。KSUIDの時刻は独自の起点を持つ秒単位です。
  • 複数端末の時計はずれます。時刻を含むIDだけで、全端末の処理順やDBへの確定順を証明することはできません。
  • GUIDはUUIDの別名として使われます。ただしバイナリ連携では、Microsoftの一部の形式とネットワークバイト順の違いに注意します。

表記と保存形式

見た目の短さと情報量は別です。復元できる符号化と、文字を削る切り詰めを区別しましょう。

表記をそろえる

  • 通常表記は8-4-4-4-12桁の16進数です。大文字と小文字は同じ値を表します。ハイフンなしを受け付けるかは入力仕様で決めます。
  • URNでは先頭にurn:uuid:を付けます。別のBase32・Base64url表記を採用するときは、文字集合・パディング・バイト順・元の128ビットを保つことを決めます。

保存形式を選ぶ

  • DBにUUID専用型があれば候補にし、なければ16バイトのバイナリや文字列を検討します。BINARY(16)なら必ず速い、とは限りません。実際の索引・照合・クエリで比較します。
  • 変換関数がUUIDv1向けにバイトを並べ替える場合があります。v7に流用する前に、往復変換とソート順を確かめます。

プライバシーと乱数品質

識別子を知っていることと、アクセスする権限があることは別です。

情報の露出を把握する

  • UUIDv1は時刻を含み、実装によってはMACアドレスも含みます。ランダムなノード値にしても時刻は隠れません。UUIDv7・ULID・KSUIDも時刻を含みます。
  • 乱数ベースのIDは、暗号学的に安全な乱数生成器を使うライブラリで生成します。UUIDを秘密のアクセス権として扱わず、認証・認可を別に実装します。

入力の検証

「UUIDらしい文字列」と「そのAPIが受け付けるUUID」を分けて確認します。

受け付ける形式を決める

  • パーサーで構造を検査し、APIが許可するバージョンとバリアントを確認します。バージョンは第3ブロックの先頭です。NilやMaxを許すかも用途ごとに決めます。
  • 構造が正しくても、レコードの存在や閲覧権限までは保証しません。保存時の一意性と、アクセス時の認可をそれぞれ確認します。

UUIDv4を生成する

Python 3または対応するNode.jsがインストールされた端末で実行します。Pythonのコマンド名がpython3の環境では読み替えてください。

Pythonで生成する

python -c "import uuid; print(uuid.uuid4())"

Node.jsで生成する

crypto.randomUUID対応版を使います。毎回異なる値が出ます。

node -e "console.log(require('node:crypto').randomUUID())"

仕様と関連記事

RFC 9562 (§4, §5.4, §5.7, §6, §8) / ULID specification / KSUID reference implementation / Python uuid / Node.js crypto.randomUUID

関連する基礎知識

UUIDの基本 / Unixタイム / ハッシュ値