ID 形式の選び方: UUID、ULID、Snowflake、自動採番
ほぼすべてのシステムは物に一意な ID を与える必要があり、その選択はずっと後になって結果として現れます — データベース性能、ID が情報を漏らすか、異なるサービスが衝突せずどれだけ容易に ID を生成できるか、において。本ガイドは一般的な形式を比較し、習慣ではなく意図して選べる方法を示します。
自動採番の整数
古典的なデータベース ID: 1、2、3 … とデータベースが払い出します。とても小さく、インデックスが速く、作成順に自然に並びます。単一のデータベースなら、たいていこれで十分です。
弱点は端で現れます。中央のデータベースだけが発行できるので、独立したサービスやオフラインのクライアントは ID を前もって生成できません。また情報を漏らします: 競合があなたの請求書番号を読んで注文数を推定でき、URL 中の連番は隣のレコードを推測するよう誘います。
UUID バージョン4(ランダム)
v4 UUID は122ビットの乱数で、通常36文字で書きます。誰でも、どこでも、調整なしに生成でき、衝突の確率は事実上ゼロなので、分散システム、マージに優しいキー、推測されては困る公開識別子に最適です。
代償はサイズと順序です。整数よりはるかに大きく、完全にランダムなので時系列ではありません — ランダムなキーを一般的な B-tree インデックスに挿入すると書き込みが散らばり、規模が大きくなるとデータベース性能を損ないえます。埋め込み情報も持たず、それは時に長所、時に制約です。
時系列 ID: UUID v7、ULID、Snowflake
より新しい系統は、先頭ビットにタイムスタンプを置いて順序問題を解決します。そのため後に生成された ID が先のものより後ろに並びつつ、グローバルに一意です。UUID v7 は標準の UUID 形式の中でこれを行います。ULID は同じことを26文字の簡潔で URL に優しく大文字小文字を区別しないエンコードで行います。Snowflake ID(Twitter が広めた)はタイムスタンプ・マシン ID・ミリ秒ごとのカウンターを64ビット整数に詰めます。
時系列はインデックスに優しい挿入と無償の時系列ソートを、中央の権威なしに与えます。トレードオフは、作成時刻が ID に見えるようになることです — たいてい無害ですが、ときに露出したくないものです。
この選択が実際に影響すること
形式を選ぶと4つの性質が一緒に動くので、明示的に比較するとよいです。
- 調整: どのノードも単独で ID を生成できる(UUID/ULID/Snowflake)か、中央データベースだけ(自動採番)か?
- 順序: ID は作成時刻で並べ替えられる(自動採番、v7、ULID、Snowflake)か、否か(UUID v4)?
- サイズとインデックスのコスト: 整数が最小; ランダム UUID が最大でインデックスに最も優しくない。
- 情報漏れ: 連番の整数は量を明かし列挙を誘う; ランダム UUID は何も明かさない; 時系列 ID はタイムスタンプを明かす。
妥当なデフォルト
データベースが一つで ID を公開しないなら、自動採番の整数が単純で効率的です。ID が公開される、多くのサービスが生成する、または URL スラッグに使うなら、UUID を選びましょう — データベース効率のためおおよそ時系列にしたいなら v7 か ULID、何も明かさないことを特に望むなら v4。
何を選ぶにせよ、一つのシステム内では一貫させ、同じ種類のエンティティに形式を混ぜないこと。最悪の ID 戦略は、たいてい偶然に決まったものです。