ULID 生成
ソート可能な 26 文字の ULID(Crockford base32)を生成し、埋め込まれたタイムスタンプを日付へデコード。データベース主キーに最適。
ソート可能な一意識別子。 ULID は 26 文字で、先頭 10 文字が作成時刻(ミリ秒)を、末尾 16 文字が乱数を表します。そのため辞書順でソートでき、主キーとして安全に使えます。ブラウザ内生成。
ソート可能な 26 文字の ULID(Crockford base32)を生成し、埋め込まれたタイムスタンプを日付へデコード。データベース主キーに最適。
ソート可能な一意識別子。 ULID は 26 文字で、先頭 10 文字が作成時刻(ミリ秒)を、末尾 16 文字が乱数を表します。そのため辞書順でソートでき、主キーとして安全に使えます。ブラウザ内生成。
ULID は UUID と同じ 128 ビット幅の識別子で、48 ビットのミリ秒タイムスタンプと 80 ビットの乱数という 2 つの部分から成ります。表記は UUID のハイフン付き 36 文字 16 進ではなく、Crockford base32 の 26 文字です。そのため短く、大文字小文字を区別せず、最も読み間違えやすい文字を含みません。アルファベットから I、L、O、U が除外されています。
本質的な違いはエンコードではなく順序性です。タイムスタンプが上位ビットを占め、base32 がバイト順を保つため、ULID を単なる文字列としてソートすると生成時刻順に並びます。同じミリ秒に生成された 2 つの ID は乱数部分で決まりますが、ミリ秒をまたげば順序は正確です。
UUIDv4 は一様な乱数であり、クラスタ化インデックスにとってはまさに避けたい性質です。挿入のたびに B ツリーのランダムな位置に着地するため、データベースはページ分割を繰り返し、コールドなページに触れ続けます。インデックスは必要以上に肥大し、テーブルの成長とともに書き込みスループットが劣化します。MySQL の InnoDB や SQL Server における UUID 主キーの問題としてよく知られています。
時刻順の識別子はインデックスの右端付近に追加されるため、アクセスパターンは自動採番の整数と同じです。ID 取得のための往復が不要、サービス間の調整が不要、シャード間のマージが安全という、クライアント生成のグローバル一意キーの利点を保ったまま、インデックスの断片化を避けられます。
RFC 9562 で標準化された UUIDv7 は、標準 UUID の書式とレイアウトのまま ULID と同じことを実現します。すでにネイティブの UUID 列型やツールが揃っているスタックなら、既存のエコシステムにそのまま収まるという理由だけで、現在は UUIDv7 のほうが適切なことが多いでしょう。URL やログで短く扱いやすいテキスト形式が欲しい場合には ULID に依然として利点があります。
いずれにせよ、タイムスタンプは ID を持つ誰にでも見えることを理解しておいてください。生成時刻は漏れ、隣接する ID は前後関係を明かします。列挙や時刻が機密にあたる用途には使わないでください。1 ミリ秒あたり 80 ビットの乱数があるため衝突は実務上の懸念ではありませんが、ULID は秘密情報ではなく、アクセストークンとして使ってはいけません。