UUID v4とv7の違い - いつどちらを使うべきか実例で解説
最終更新日: 2026年4月19日
「UUIDは v4 を使っておけば安全」と思われがちですが、DBのプライマリキーに使うと書き込み性能が劇的に落ちることがあります。 2024年5月に標準化された UUID v7(RFC 9562)は、v4の衝突耐性と 時系列ソート性を両立する新しい選択肢です。 この記事ではv4とv7の違い、実務での使い分け、ULIDとの比較までを整理します。
図1: UUID v4 と v7 のビット構造
f47ac10b-58cc-4372-a567-0e02b2c3d479018f4d1a-3b2c-7abc-8def-1234567890abv7は先頭48ビットがUnix時刻(ミリ秒)なので、生成順にソートされる
v4とv7の性能差:なぜ重要か
MySQL InnoDB や PostgreSQL などB-treeベースのDBは、プライマリキーが単調増加だと インデックスへの挿入がほぼ末尾追記となり高速です。 完全ランダムなUUID v4をプライマリキーにすると、インデックスの任意の位置に挿入が発生し、 ページ分割(page split)とI/Oが増えます。 大規模テーブルでは書き込みスループットが数倍〜十数倍悪化する報告が 複数のベンチマーク記事で共有されています(Percona, CockroachDBなど)。
UUID v7は先頭48ビットがタイムスタンプなので、ミリ秒単位で見ればソート済みに近い順序で挿入されます。 結果としてページ分割が抑えられ、v4に比べて書き込み性能は明確に改善します。 同時にv4同様の衝突耐性(74ビットのランダム領域)も維持されます。
使い分けの指針
| 用途 | 推奨 | 理由 |
|---|---|---|
| DBのプライマリキー | v7 | 書き込み性能・範囲検索性能 |
| 公開URLのリソースID | v4 | 生成時刻を推測されたくない |
| トレース/リクエストID | v4 または v7 | ログ解析で時系列ソートしたいならv7 |
| セッションID / トークン | UUIDは使わない | 暗号学的乱数(crypto.randomBytes(32)等) |
| 分散システムのイベントID | v7 または ULID | 時系列+衝突耐性 |
注意点として、セッションIDやCSRFトークンにUUIDを使ってはいけません。 UUID v4は暗号学的に強い乱数で生成されるとは限らず(実装依存)、v7は先頭が時刻で推測可能です。 認証系には crypto.randomBytes(32) 相当の専用乱数を使ってください。
生成方法(言語別)
JavaScript / TypeScript
// v4: 標準API
const v4 = crypto.randomUUID();
// v7: Node.js 23.2.0 以降は標準
// 古い環境では uuid パッケージを使用
import { v7 as uuidv7 } from "uuid";
const v7 = uuidv7();
// "018f4d1a-3b2c-7abc-8def-1234567890ab"Python
# v4: 標準
import uuid
print(uuid.uuid4())
# v7: Python 3.14 以降は標準
# 3.13以前は uuid6 / uuid7 パッケージ
# pip install uuid7
from uuid_extensions import uuid7
print(uuid7())PostgreSQL
-- PostgreSQL 18 から gen_random_uuid() に加え uuidv7() が標準関数化予定
-- 17以前は uuid-ossp 拡張や pg_uuidv7 拡張を利用
CREATE EXTENSION IF NOT EXISTS "pg_uuidv7";
CREATE TABLE orders (
id uuid PRIMARY KEY DEFAULT uuid_generate_v7(),
created_at timestamptz NOT NULL DEFAULT now()
);※ PostgreSQL公式ロードマップは流動的です。使用前にお使いのバージョンで最新の関数名をご確認ください。
図2: UUIDバージョンの選び方
crypto.randomBytes(32)ULIDとの比較
ULIDもUUID v7と同じ「時刻プレフィックス + ランダム」構造を持つ識別子です。 主な違いはエンコーディング:
- UUID v7: 128ビット、16進表記(36文字、ハイフン入り)。 標準規格(RFC 9562)、DB・言語の標準サポートが進行中。
- ULID: 128ビット、Crockford's Base32(26文字、ハイフンなし)。 短く、URL-safe、人間が写経しやすい。標準化団体による仕様はないが採用例多数。
既存のUUIDカラムやUUIDフォーマットのエコシステムに乗せたいならv7、 URLや管理画面で短く見せたいならULID、という棲み分けが現実的です。 新規プロジェクトで迷うなら、標準規格である v7 を選んでおくと後々の選択肢が広いです。
衝突確率の実務的な目安
v4のランダム部は122ビット、v7は74ビット。 バースデー問題の近似で「50%衝突するのに何個生成する必要があるか」を計算すると:
- UUID v4: 約 2.71 × 1018 個
- UUID v7(同一ミリ秒内): 約 1.55 × 1011 個
v7は「同一ミリ秒内で」1,500億個という条件なので、単一サーバで普通に使う限り衝突は現実的に起きません。 大規模分散環境で1ms内に億単位のID生成が発生する場合のみ、実装側で 「同一ミリ秒内のカウンタ領域を確保する」などの対策が行われています(RFC 9562 8.1参照)。
デバッグTips
UUIDの先頭を見ればバージョンが判別できます。
f47ac10b-58cc-4372-a567-0e02b2c3d479
^
4 → UUID v4
018f4d1a-3b2c-7abc-8def-1234567890ab
^
7 → UUID v7v7の先頭12桁は16進のUnixミリ秒タイムスタンプです。0x018f4d1a3b2c を10進変換すると生成時刻が得られます。 本サイトのUUID Generatorで v4・v7を即座に生成できるので、動作確認にお使いください。
まとめ
UUID v7は「DBプライマリキーに使えるUUID」として事実上の標準になりつつあります。 v4の完全ランダム性が必要な用途(公開URL、推測回避)以外では、v7を選ぶのが合理的です。 ただし認証系には絶対に使わず、専用の暗号学的乱数を使うこと。 ここさえ押さえておけば、IDの選択で大きく外すことはありません。