DevToolBox

UUID v4とv7の違い - いつどちらを使うべきか実例で解説

最終更新日: 2026年4月19日

「UUIDは v4 を使っておけば安全」と思われがちですが、DBのプライマリキーに使うと書き込み性能が劇的に落ちることがあります。 2024年5月に標準化された UUID v7(RFC 9562)は、v4の衝突耐性と 時系列ソート性を両立する新しい選択肢です。 この記事ではv4とv7の違い、実務での使い分け、ULIDとの比較までを整理します。

図1: UUID v4 と v7 のビット構造

UUID v4(完全ランダム)
ランダム
122 bit
Ver
4 bit
Var
2 bit
例: f47ac10b-58cc-4372-a567-0e02b2c3d479
UUID v7(タイムスタンプ + ランダム)
Unix ms
48 bit
Ver
4 bit
ランダム
74 bit
Var
2 bit
例: 018f4d1a-3b2c-7abc-8def-1234567890ab

v7は先頭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のリソースIDv4生成時刻を推測されたくない
トレース/リクエストIDv4 または v7ログ解析で時系列ソートしたいならv7
セッションID / トークンUUIDは使わない暗号学的乱数(crypto.randomBytes(32)等)
分散システムのイベントIDv7 または 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バージョンの選び方

Q1. 認証・セッション・CSRF用途?
YES → UUIDを使わないcrypto.randomBytes(32)
NO → Q2へ
Q2. 生成時刻をクライアントに知られたくない?
YES → UUID v4
NO → Q3へ
Q3. DBのプライマリキー or 時系列ソートしたい?
YES → UUID v7(または ULID)
NO → UUID v4 で十分

ULIDとの比較

ULIDもUUID v7と同じ「時刻プレフィックス + ランダム」構造を持つ識別子です。 主な違いはエンコーディング:

既存のUUIDカラムやUUIDフォーマットのエコシステムに乗せたいならv7、 URLや管理画面で短く見せたいならULID、という棲み分けが現実的です。 新規プロジェクトで迷うなら、標準規格である v7 を選んでおくと後々の選択肢が広いです。

衝突確率の実務的な目安

v4のランダム部は122ビット、v7は74ビット。 バースデー問題の近似で「50%衝突するのに何個生成する必要があるか」を計算すると:

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 v7

v7の先頭12桁は16進のUnixミリ秒タイムスタンプです。0x018f4d1a3b2c を10進変換すると生成時刻が得られます。 本サイトのUUID Generatorで v4・v7を即座に生成できるので、動作確認にお使いください。

まとめ

UUID v7は「DBプライマリキーに使えるUUID」として事実上の標準になりつつあります。 v4の完全ランダム性が必要な用途(公開URL、推測回避)以外では、v7を選ぶのが合理的です。 ただし認証系には絶対に使わず、専用の暗号学的乱数を使うこと。 ここさえ押さえておけば、IDの選択で大きく外すことはありません。

関連ツール・ガイド