UUIDとULIDの違い:どちらを使うべきか

UUID v4・UUID v7・ULIDの仕組みとビット構成の違いを比較し、データベースの主キーとしてどれを選ぶべきかを解説します。

公開日:
UUID v4・UUID v7・ULIDのビット構成比較図

UUIDとULID、何が違うのか

「ID生成にUUIDを使うべきか、それともULIDを使うべきか」は、データベース設計やAPI設計でしばしば議論になるテーマです。 どちらも「世界中で重複しない一意な識別子」という目的は同じですが、内部のビット構成と、それによって得られる性質(特にソート可能かどうか)が大きく異なります。 この記事では、UUID v4・UUID v7・ULIDの3つを軸に、仕組みの違いと使い分けの指針を整理します。

早見表

UUID v4・UUID v7・ULIDのビット構成を横棒グラフで比較した図。ULIDとUUID v7は先頭48ビットがタイムスタンプ、UUID v4は全体がランダム値であることを示している。

UUID v4 UUID v7 ULID
標準化 RFC 9562(旧RFC 4122) RFC 9562(2024年制定) コミュニティ仕様(IETF標準ではない)
ビット構成 122ビットのランダム値+バージョン/バリアント6ビット 48ビットのUnixタイムスタンプ(ミリ秒)+74ビットのランダム値 48ビットのUnixタイムスタンプ(ミリ秒)+80ビットのランダム値
文字列表現 36文字(8-4-4-4-12のハイフン区切り16進数) 36文字(UUIDと同じハイフン区切り形式) 26文字(Crockfordの Base32、ハイフンなし)
生成順ソート 不可(完全ランダムなため順序性がない) 可能(先頭がタイムスタンプのため辞書順=生成順になる) 可能(同上)
既存UUID型カラムとの互換性 そのまま利用可能 そのまま利用可能(正式なUUIDバージョンのため) 文字列としては26文字なので、DBのUUID型に入れるには変換が必要

それぞれの仕組み

UUID v4:完全ランダムな128ビット

UUID v4は、128ビットのうちバージョン・バリアントを示す6ビットを除いた122ビットを、暗号学的に安全な乱数で埋めて生成します。 「いつ生成されたか」という情報を一切含まないため、生成順に並べ替えることはできません。一方で、ランダム性のみに依存しているため実装がシンプルで、あらゆる言語・DBで枯れたサポートがあるのが強みです。

UUID v7:タイムスタンプ付きの標準UUID

UUID v7は2024年に標準化されたRFC 9562で定義された、比較的新しいUUIDのバージョンです。先頭48ビットにミリ秒精度のUnixタイムスタンプを埋め込み、残り74ビットをランダム値で埋めます。 タイムスタンプが先頭にあるため、生成したUUID v7を文字列として単純にソートするだけで生成順(時系列順)に並びます。それでいて8-4-4-4-12のハイフン区切り形式そのままなので、既存のUUID型カラムやUUID対応ライブラリと完全に互換性があります。

ULID:Base32で表現する時系列ソート可能ID

ULID(Universally Unique Lexicographically Sortable Identifier)は、UUID v7が標準化される前から使われてきた、コミュニティベースの仕様です。ビット構成はUUID v7とよく似ており、先頭48ビットがミリ秒精度のUnixタイムスタンプ、残り80ビットがランダム値です。 最大の違いは文字列表現で、Crockfordの Base32エンコーディングを使い、ハイフンなしの26文字(タイムスタンプ10文字+ランダム値16文字)で表現します。ILOUのような見間違えやすい文字を除いたアルファベットを使うため、人が目視で読み書きしてもミスが起きにくく、UUIDの36文字より短くURLにも埋め込みやすいという特徴があります。

なぜ「ソート可能かどうか」が重要なのか

UUID v4のような完全ランダムなIDを主キーに使うと、新しく挿入される行のID値がインデックス内のランダムな位置に散らばります。これにより、B-treeインデックスのページ分割が頻発し、書き込みのたびにキャッシュに乗っていないページへのアクセスが発生しやすくなります。テーブルの行数が増えるほど、この影響は無視できないパフォーマンス劣化として表れます。

一方、UUID v7やULIDのようにタイムスタンプを先頭に持つIDは、新しい行のIDが常に既存の最大値より大きくなるため、インデックスの末尾に追記される形になります。オートインクリメントの整数主キーに近い書き込み特性を持ちながら、複数サーバーでの分散生成(中央の採番サーバーが不要)というUUID本来の利点も維持できます。

注意点:タイムスタンプの埋め込みはトレードオフでもある

UUID v7やULIDが持つ「生成時刻を埋め込む」という性質は、データベースの主キーとしては利点ですが、IDそのものを外部に公開する場面では情報漏えいのリスクになり得ます。IDを見ただけでレコードがいつ作られたかが分かってしまうためです。

そのため、パスワードリセット用のトークンやセッションID、招待コードのように「推測されては困る」用途には、時系列性を持たないUUID v4や、十分な長さを持つランダム文字列を使うのが無難です。逆に、データベースの主キーやイベントログのID、内部的な採番など、ソート可能性のメリットが大きく外部に直接公開しない用途では、UUID v7やULIDが向いています。

まとめ:使い分けの指針

  • 既存システムとの互換性を最優先したい/時系列ソートは不要:UUID v4
  • DBの主キーとして使いたいが、既存のUUID型カラムやライブラリともそのまま互換性を持たせたい:UUID v7
  • DBの主キーとして使いたく、文字列を短くしたい/人が目視で読み書きする場面がある:ULID
  • 外部に公開するトークンやセッションIDなど、生成時刻を推測されたくない用途:UUID v4(またはランダム文字列)

Torinoa Toolsで試す

それぞれの生成・検証は、ブラウザだけで完結する以下のツールで試せます。データは一切サーバーへ送信されません。