0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UUIDv4 vs UUIDv7: データベース性能を劇的に改善する方法

Posted at

はじめに

プライマリキーを連番(1, 2, 3...)からUUIDに変更したら、データベースの書き込み性能が大幅に劣化した経験はありませんか?

この記事では、UUIDv4とUUIDv7の違いと、なぜv7を使うべきなのかを解説します。


UUIDの普及状況

現状

UUIDv4が圧倒的に普及しています

理由

  • 最もシンプル(ランダム生成するだけ)
  • ライブラリのデフォルトになっていることが多い
  • 歴史的に長く使われてきた

UUIDv7について

2024年5月にRFC 9562で標準化されたばかりで、これから普及していく段階です。


フォーマットの違い

UUIDv4(ランダム)

a1b2c3d4-e5f6-4789-a012-b3c4d5e6f789
         ^^^^    ^
         |       |
         バージョン4  バリアント

特徴

  • 完全にランダム
  • 順序性なし
  • 例: f47ac10b-58cc-4372-a567-0e02b2c3d479

UUIDv7(タイムスタンプベース)

018c7e1a-2b3c-7def-8901-234567890abc
^^^^^^^^^^^^^    ^
|                |
タイムスタンプ      バージョン7
(ミリ秒精度)

特徴

  • 先頭48ビット: Unixタイムスタンプ(ミリ秒)
  • 残り: ランダム
  • 例: 018c7e1a-2b3c-7def-8901-234567890abc

実際の比較

# 同じ時間に生成したUUID

【UUIDv4】
550e8400-e29b-41d4-a716-446655440000
9b6d5e2a-1c3f-4d8e-9a7b-3c2d1e0f9a8b  ← バラバラ
c8f7e6d5-4b3a-4291-8807-f6e5d4c3b2a1

【UUIDv7】
018c7e1a-2b3c-7001-8901-234567890abc
018c7e1a-2b3c-7002-8902-345678901bcd  ← 順序性がある
018c7e1a-2b3c-7003-8903-456789012cde

なぜUUIDv4は性能が悪いのか

データベースのインデックスは多くの場合B-Tree(バランス木)構造を使用しています。

連番IDの場合(1, 2, 3...)

✅ 新しいデータは常にインデックスの最右端に追加される
✅ 書き込みは予測可能で順次的
✅ キャッシュヒット率が最大化
✅ ページは100%満杯に保たれる

UUIDv4の場合

❌ ランダムな値なので、挿入位置がツリー内のどこにでも発生
ランダムI/Oが発生(ディスクから常にランダムなページをメモリにロード)
ページ分割が頻発(ページが満杯になると半分に分割)
スイスチーズ効果(インデックスが穴だらけになり、RAMとディスク容量を浪費)

なぜデータベースサイズが重要なのか

データベースは頻繁にアクセスするデータをRAM(メモリ)にキャッシュしています。

【データベース ≦ RAM の場合】
✅ すべてのインデックスページがメモリ内
✅ UUIDv4でもメモリ内で完結
✅ 性能劣化は比較的小さい

【データベース > RAM の場合】
❌ インデックスの一部しかメモリにない
❌ UUIDv4のランダムアクセスでメモリにないページへアクセス
❌ ディスクI/Oが頻発(メモリの約100,000倍遅い)
❌ 書き込み性能が20-90%劣化

連番IDやUUIDv7の場合

データベースサイズがRAMを超えても、新しいデータは常に最新ページ(最右端)に追加されるため、最新ページだけメモリに保持すればよく、ディスクI/Oは最小限で済みます。

結果

インデックスサイズがRAMを超えると、UUIDv4は書き込み性能が20-90%劣化する可能性


UUIDv7の利点

UUIDv7はタイムスタンプを先頭に埋め込むことで、この問題を解決します。

1. 書き込み性能が大幅改善

  • タイムスタンプベースで単調増加するため、B-Treeインデックスの最右端に追加される
  • ページ分割が激減し、インデックスの断片化を防げる
  • UUIDv4と比較して20-90%の性能劣化を回避できる

2. 分散生成が可能

  • 中央集権的なカウンターが不要
  • 複数のサーバーやアプリケーションインスタンスで独立して生成できる

3. 列挙攻撃への耐性

  • 連番(1, 2, 3...)と違い、次のIDを推測されにくい

UUIDv7のデメリット

タイムスタンプの漏洩

❌ UUIDv7はレコード作成時刻を含むため、その情報が推測可能
❌ セキュリティ要件によっては問題になる可能性

ただし

タイムスタンプ漏洩が致命的なセキュリティリスクになるケースは稀です。


トレードオフの整理

項目 UUIDv4 UUIDv7
書き込み性能 ❌ 劣化(20-90%) ✅ 良好(連番並み)
分散生成 ✅ 可能 ✅ 可能
列挙攻撃耐性 ✅ 強い ✅ 強い
タイムスタンプ秘匿 ✅ 秘匿 ❌ 漏洩
インデックス断片化 ❌ 発生 ✅ 発生しない

失うもの

  • タイムスタンプの秘匿性(いつ作成されたかがバレる)

得るもの

  • 書き込み性能の大幅改善(20-90%の劣化を回避)
  • インデックスの断片化防止
  • ディスクI/Oの削減
  • RAMの効率的な使用

結論

基本方針

タイムスタンプ漏洩のリスクよりも、性能面のメリットの方が圧倒的に大きい

UUIDv7への移行を強く推奨するケース

  1. 書き込み性能が重要なアプリケーション

    • 高頻度の書き込みが発生する
    • レスポンスタイムが重要
  2. データベースが成長していく見込みがある

    • 将来的にRAMを超えるサイズになる可能性
    • スケーラビリティを事前に確保したい
  3. 分散システムでIDを生成する必要がある

    • 複数サーバーで独立してID生成
    • 中央カウンターを避けたい
  4. すでにUUIDv4で性能問題が発生している

    • 書き込み性能が劣化している
    • インデックスの肥大化が問題になっている

移行戦略

新規プロジェクト
最初からUUIDv7を採用することで、将来の性能問題を予防できます。

既存システム
新規テーブルや重要なテーブルから段階的にUUIDv7へ移行する価値があります。


参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?