日本語

開発者ツール · UUID ジェネレーター

ULID、Snowflake、KSUID、および UUIDv7: ソート可能な ID の比較

· 背景

uuid 暗号化 ブラウザ API

4 つの識別子レイアウトを並べて表示: ULID、Snowflake、KSUID、および UUIDv7、タイムスタンプとランダム性セクションを表示
オリジナル ToolAcre ベクトル イラスト

ランダム UUID は作成時間によって並べ替えられないため、いくつかの形式ではタイムスタンプが最初に配置されます。この記事では、レイアウト、サイズ、単調性、互換性に関して ULID、Snowflake、KSUID、UUIDv7 を比較します。

ランダム ID とそれを嫌うインデックス — 時系列識別子が解決する問題

ランダムな v4 UUID は、新しいレコードが到着すると B ツリーの主キー全体に挿入ポイントを分散させ、ページの分割と再編成を引き起こします。ランダムな位置に挿入すると、書き込みパフォーマンスが低下し、ディスクの断片化が大幅に増加します。高スループットのデータベースは、このコスト (真に独立した調整されていない識別子の代償) を許容しますが、コストは現実のものです。 UUID を作成時間で並べ替える必要がある場合は、タイムスタンプ プレフィックスを追加することでインデックスの特性を大幅に改善できます。 ULID、Snowflake、KSUID、RFC 9562 v7 など、いくつかの形式が登場しました。それぞれは、サイズ (26 文字から 128 ビット)、タイムスタンプの精度 (秒からナノ秒)、UUID の互換性、および ID ジェネレーターの調整に一元化が必要かどうかに関して、異なるトレードオフを行います。データベースのベンチマークでは、挿入パフォーマンスが大幅に向上していることが示されています。

ULID — 48 ビットのミリ秒タイムスタンプと、26 Crockford Base32 文字の 80 ランダム ビット (単調オプション付き)

ULID (Universally Unique Lexicographically Sortable Identifier) は、48 ビットのミリ秒タイムスタンプと 80 ビットのランダム ペイロードを Crockford Base32 の 26 文字でエンコードします。テキスト表現は辞書編集順に正しくソートされるため、ULID はタイムスタンプの順序と読みやすさが重要となるシステム、つまりログ処理、分散トレース、人が直接見る出力で識別子を簡単に読み取れる必要があるマイクロサービスに適しています。 ULID は、同じミリ秒内に生成された複数の識別子が繰り返すのではなくランダムな部分を増分する単調なバリアントを提供し、急速な ID バーストでも厳密な生成順序を維持します。トレードオフとして、ULID は UUID ではありません。エンコード変換を行わないと、標準の 128 ビット UUID データベース列に適合しません。 ULID の精度は約 8925 年をカバーします。

Snowflake — タイムスタンプ、ワーカー ID、シーケンスからの 64 ビット ID、およびそれらに必要な調整

Snowflake は、もともと Twitter によって設計された 64 ビットの識別子で、41 ビットのミリ秒タイムスタンプ、10 ビットのワーカー ID、12 ビットのシーケンス番号として構造化されています。 41 ビットのタイムスタンプは約 69 年をカバーし、2106 でオーバーフローするため、エポック調整と移行計画が必要です。ワーカー ID は、さまざまなサーバーまたはプロセスによって生成された識別子を区別します。各 Snowflake ジェネレーターは、他のものと競合することなく、独自の一意のワーカー ID を認識している必要があります。 Snowflake は 128 ではなく 64 ビットなので、UUID の半分のサイズになり、インデックス作成が速くなり、識別子ごとのストレージ効率が高くなります。時間とワーカー ID で並べ替えられるため、ソースごとにリクエストやログをルーティングするのに役立ちます。欠点は運用上です。すべてのジェネレーターにワーカー ID を割り当てる必要があり、クロックを同期しておく必要があります。

KSUID — バイトとしてソートされた、大きなランダム ペイロードを含む秒のタイムスタンプ

KSUID (K-Sortable Unique Identifier) は、32 ビットの Unix の 2 番目のタイムスタンプと 96 ビットのランダム ペイロードで構成される 128 ビットの識別子で、通常は 27 Base62 文字としてエンコードされます。この形式は辞書編集順にソート可能であり、ランダム部分はそのサイズに対して暗号的に健全です。 KSUID は ULID や Snowflake ほど広く採用されていませんが、独特のセマンティクスを提供します。タイムスタンプは人間が判読できる秒に簡単にデコードされ (ログやデバッグに役立ちます)、96 ビットのランダム部分は十分に大きいため、同じ秒内に生成される複数の KSUID は、シーケンス調整なしで重複確率が事実上ゼロになります。 Snowflake とは異なり、KSUID ではワーカー ID の調整や一元的な割り当ては必要ありません。 KSUID はミリ秒ではなく秒で動作するため、追加のロジックを実装しない限り、1 秒以内の複数の ID はランダムに並べ替えられます。

UUIDv7 — 既存の uuid 列とツールに適合する標準化トラックの回答

RFC 9562 v7 は、48 ビットの Unix ミリ秒タイムスタンプ、サブミリ秒精度の 12 ビット (シーケンス カウンターとして使用可能)、および 62 ランダム ビットをすべて組み合わせた 128 ビットの識別子です。辞書編集文字列としても、データベース内の 128 ビット バイトとしても正しくソートされます。重要なのは、これが有効な UUID であることです。バージョン ニブルを 7 に設定し、バリアント ビットを RFC 9562 標準に設定し、UUID を処理するすべてのツール、データベース列、および API との互換性を確保します。エンコーディングの変換は必要なく、既存の UUID インフラストラクチャを変更する必要はありません。複数の v7 識別子が同じミリ秒内に生成される場合、RFC 9562 では、サブミリ秒フィールドをランダム ビットではなく単調カウンターとして使用することを推奨しています。 V7 は、UUID の互換性を維持するための実用的な選択を表しています。

1 ミリ秒以内の単調性 — 各フォーマットがバーストを処理する方法と、それが順序保証にとって重要である理由

単調性とは、2 つのイベントが観測可能な順序で発生した場合、それらの ID が同じ順序で比較されるという特性です。最新のハードウェアではミリ秒レベルの粒度で、同じクロックティック内で複数のイベントが日常的に発生するため、ソート可能な ID スキームはミリ秒未満の順序付けを正しく処理する必要があります。 ULID は、ランダム化の代わりにランダム部分が増加する明示的な単調モードを提供します。 Snowflake には、ミリ秒単位で増加する 12 ビットのシーケンス番号が含まれています。 KSUID には組み込みメカニズムがないため、追加のロジックが追加されない限り、1 秒未満のイベントはランダムに並べ替えられます。 RFC 9562 v7 では、サブミリ秒フィールドを単調カウンターとして使用することを推奨しています。システムが 1 秒あたり数千の UUID を生成する場合、ミリ秒以内の単調性がクエリの順序に大きな影響を与えます。

これでカバーされないもの — スループットのベンチマーク。これはハードウェアと言語に依存します。投稿は定性的なものにとどまる

スループット ベンチマークとパフォーマンス データは、ハードウェア アーキテクチャ、言語実装、データベース エンジン、およびキャッシュ戦略に大きく依存するため、含まれていません。データベースのパフォーマンス特性は、ランダムな挿入、範囲クエリ、インデックスのオーバーヘッド、現実的な運用負荷の下での合計スループットを測定するかどうかによって大きく異なります。この投稿は定性的なものであり、誤解を招く可能性のある環境固有の数値を提供するのではなく、設計に基づいて概念的にフォーマットを比較しています。実際のパフォーマンス評価には、独自のワークロード、コードベース、運用上の制約を使用して独自の環境でテストする必要があります。さまざまな ID 形式のベンチマークを行うことは価値のある演習です。

要点: 多くの場合、互換性が決定します。ToolAcre ジェネレーターはランダムな UUID を生成します。整形式チェックを使用して、ライブラリの UUIDv7 が UUID として解析されることを確認します。

互換性によって、どの形式を選択するかが決まります。データベース スキーマに既に UUID 列が必要な場合、v7 は UUID エコシステムを離れることなく並べ替え可能性を実現する最新の答えです。カスタム ID タイプを使用して新しいシステムを構築する場合、ULID はより小さいテキスト表現とミリ秒の精度の利点を提供します。 64 ビットのストレージが必要で、一元的な割り当てを通じてワーカー ID の調整を管理できる場合は、大容量システムでの Snowflake の選択肢が実証済みです。基本的なトレードオフは、標準互換性 (v7 の選択) と、より小さいサイズ (Snowflake) や Base32 の可読性 (ULID) などの代替プロパティとの間です。システムの制約とエコシステムの決定に基づいて選択を行います。