ULID 生成ツール

オンラインで ULID を生成します。48ビットのタイムスタンプと80ビットのランダム値からなる、CrockfordのBase32でエンコードされた26文字のIDです。

フォーマット
生成された ID
準備完了。ブラウザ上で ULID を生成します。

IDの構造

レイアウト
CrockfordのBase32文字セットを用いた26文字。最初の10文字が時間、続く16文字がランダムな値です。
エントロピー
48ビットのミリ秒単位のタイムスタンプの後に、80ビットのランダムデータが続きます。
時間
はい、含まれます。最初の10文字にミリ秒単位の生成時間がエンコードされているため、辞書順でのソートが時系列ソートと一致します。
衝突リスク
ランダム部分には80ビットが割り当てられています。衝突リスクは、主に同一ミリ秒内にどれだけのIDが生成されるかに依存します。
生成例
01M12BRPYCQ8YS43EA0EYRF5RH

ID は強力なブラウザの乱数生成器を使用してローカルで生成されます。BroBroGo に送信されることはありません。

よくある質問

ULIDはどのような用途に適していますか?

ULIDはコンパクトでURLに適しており、プレーンテキストとして時間順にソート可能です。ログ、オブジェクトのキー、作成日時順に並べ替えたいレコードの識別子に最適です。

ULIDとUUID v7は同じものですか?

いいえ、異なります。どちらもミリ秒単位のタイムスタンプを含みますが、ULIDはCrockfordのBase32を用いた26文字であるのに対し、UUID v7 は標準的なUUIDの16進数形式(36文字)を維持します。

ULID生成ツール:構造・特性・利用ガイド

ULIDの内部構造:128ビットをどう分割するか

ULID(Universally Unique Lexicographically Sortable Identifier)は、128ビットのデータを26文字の文字列にエンコードした識別子です。この128ビットは明確に二つの部分に分割されます。

  • 先頭10文字(48ビット):ミリ秒精度のタイムスタンプ。Unixエポック(1970年1月1日 00:00:00 UTC)からの経過ミリ秒数をCrockfordのbase32でエンコードしたものです。
  • 残り16文字(80ビット):暗号論的乱数によって生成されたランダム成分。

例えば、01ARZ3NDEKTSV4RRFFQ69G5FAV というULIDの場合、01ARZ3NDEK がタイムスタンプ部分、TSV4RRFFQ69G5FAV がランダム部分です。この分割により、ULIDは生成時刻で辞書順にソート可能になります。ただし、同一ミリ秒内で生成された複数のULIDの順序はランダム成分に依存するため、厳密な生成順序は保証されません。

タイムスタンプ部分は約7.7×10^13ミリ秒(約2,400年)をカバーできるため、現実的な使用期間ではオーバーフローの心配は不要です。

Crockfordのbase32:なぜ大文字小文字を区別せず、ハイフンがないのか

ULIDはCrockfordのbase32という特定のアルファベットを使用します。このアルファベットは以下の文字で構成されています。

  • 数字:0〜9
  • 英字:A〜Z から I、L、O、U を除外したもの(つまり A B C D E F G H J K M N P Q R S T V W X Y Z)

これにより、視覚的に紛らわしい文字が排除されます。例えば、1(数字の1)と I(大文字のアイ)、0(ゼロ)と O(オー)などが混同されにくくなります。

さらに、Crockfordのbase32は大文字と小文字を区別しません。つまり、aAbB はすべて同じ値として扱われます。これは手動入力や読み上げ時のミスを減らす設計です。

UUIDと異なり、ULIDにはハイフンが含まれません。UUIDは xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx のような形式ですが、ULIDは 0123456789ABCDEFGHJKMNPQRSTVWXYZ の32文字からなる26文字の連続した文字列です。これにより、コピー&ペーストが容易になり、URLに埋め込んでもエスケープ不要です。実際、ULIDに使われる文字はすべてRFC 3986で「 unreserved characters」と定義されており、URLのパスやクエリパラメータにそのまま使用できます。

UUID v4 / v7 との比較:長さ、ソート可能性、表現

UUIDとULIDの主要な違いは以下の表の通りです。

項目 UUID v4 UUID v7 ULID
文字数 36(ハイフン込み) 36(ハイフン込み) 26(ハイフンなし)
ビット数 128 128 128
タイムスタンプ なし(完全ランダム) あり(ミリ秒精度、48ビット) あり(ミリ秒精度、48ビット)
ランダム部分 122ビット 74ビット 80ビット
ソート可能性 なし 時間順にソート可能 時間順にソート可能
大文字小文字 通常大文字で表現されるが、規定なし 同左 規定により大文字小文字を区別しない
ハイフン 5つのグループに分割 同左 なし
使用アルファベット 16進数(0-9、A-F) 同左 Crockfordのbase32(0-9、A-ZからI, L, O, U除外)

UUID v4は完全にランダムなため、データベースのインデックス(特にB-tree)でランダム挿入が発生し、断片化やパフォーマンス低下を招くことが知られています。一方、ULIDやUUID v7はタイムスタンプが先頭にあるため、新しく生成されるIDはおおよそ昇順になり、B-treeのリーフページへの挿入が効率的です。

UUID v7は2024年にRFC 9562として標準化され、ULIDと似たタイムスタンプ先頭方式を採用しています。しかし、UUID v7は依然として36文字のハイフン付き形式を取るため、ULIDの26文字という短さには及びません。ULIDはUUID v7と比較して約28%短いことになります。

ソート動作と同一ミリ秒内の制限

ULIDは辞書順(文字列としての比較)でソート可能です。0000000000 に近いほど古いタイムスタンプを、7ZZZZZZZZZ に近いほど新しいタイムスタンプを表します。この性質により、データベースのプライマリキーとして使うと、物理的な挿入位置が連続しやすくなります。

ただし注意すべき点があります。同一ミリ秒内で生成された複数のULIDの順序は保証されません。例えば、同じミリ秒に生成された 01ARZ3NDEKTSV4RRFFQ69G5FAV01ARZ3NDEKTSV4RRFFQ69G5FAW では、タイムスタンプ部分が同一なので、ランダム部分の大小で順序が決まります。この順序は生成時刻とは無関係です。非常に高いスループットでIDを生成するシステム(例:1ミリ秒に数千件)では、この制限を認識しておく必要があります。

日本語の環境でこのツールを使う場合、I(アイ)、L(エル)、O(オー)、U(ユー)がアルファベットから除外されている点も重要です。これらを使わないことで、手書きや音声での伝達ミスが減ります。ただし、Crockfordのbase32では I1 として、O0 として解釈することもできるため、実装によっては入力時に柔軟性を持たせることができます。

衝突確率と乱数生成の実際

ULIDのランダム成分は80ビットです。これは約1.2×10^24通りの値を取ります。誕生日のパラダイム(Birthday paradox)を考慮すると、約2^40(約1兆)個のULIDを生成した時点で衝突確率が50%に達します。実際には、生成数が数百万のオーダーであれば衝突確率は無視できるほど小さいと言えます。

このツールはブラウザ上で動作し、crypto.getRandomValues() を使用して乱数を生成します。これはブラウザが提供する暗号論的乱数生成器(CSPRNG)であり、予測不可能性が高いです。生成されたULIDはサーバーに送信されず、すべてローカルで処理されます。したがって、プライバシー上の懸念はなく、オフライン環境でも動作します。

生成可能な数は1~100の範囲に制限されています。これはユーザーインターフェース上の制約であり、技術的な上限ではありません。100個を超える数が必要な場合は、複数回に分けて生成するか、プログラムで直接ULIDを生成する方法を検討します。

データベースインデックスとURLセーフティの実際

ULIDの最大の実務上の利点は、データベースのプライマリキーとしての振る舞いです。ランダムなUUID v4をプライマリキーにすると、B-treeインデックスはランダムな位置に新しいエントリを挿入するため、ページ分割が頻発し、挿入性能が低下します。一方、ULIDはタイムスタンプ順にソートされるため、新しい行は常に最後尾付近に挿入され、インデックスのメンテナンスが効率的になります。

特にPostgreSQLやMySQLでプライマリキーにULIDを使う場合、UUID v4と比較して顕著な書き込み性能の向上が期待できます。実際のベンチマークでは、挿入速度が2倍以上になるケースもあります。

URLセーフティの点では、ULIDの文字セットはすべてURL unreserved文字(RFC 3986)に含まれます。つまり、ULIDをURLのパスやクエリパラメータに含めても、パーセントエンコーディング(%xx形式への変換)は一切不要です。例えば、https://example.com/resource/01ARZ3NDEKTSV4RRFFQ69G5FAV のようにそのまま使えます。これは、UUIDのハイフンがURL内で問題にならないのと同様ですが、ULIDはさらに文字数が少ないという利点があります。

よくある質問(FAQ)

Q: ULIDとUUIDのどちらを使うべきですか?

A: 識別子を生成時刻でソートする必要がある場合、または文字数を減らしたい場合はULIDが適しています。完全なランダム性が必要で、ソート可能性が不要な場合はUUID v4でも構いません。UUID v7はULIDと似た特性を持ちますが、36文字と長めです。

Q: 同じミリ秒で複数のULIDを生成した場合、順序はどうなりますか?

A: タイムスタンプ部分が同一なので、ランダム部分の値によって順序が決まります。生成時刻の前後関係は保証されません。厳密な生成順序が必要な場合は、カウンターを組み合わせた別の方式(例:Snowflake)を検討してください。

Q: ULIDの大文字と小文字はどう扱われますか?

A: Crockfordのbase32の仕様により、大文字と小文字は同一視されます。ツールで生成されるULIDは通常大文字ですが、小文字で入力しても同じ値として解釈できます。

Q: 生成できる数の上限はなぜ100ですか?

A: このツールのUI上の制限です。一度に大量のIDを生成すると操作性が低下するため、1~100の範囲に設定しています。プログラムで大量生成が必要な場合は、専用ライブラリを使用してください。

Q: ULIDはURLでエスケープが必要ですか?

A: いいえ。ULIDで使われる文字(0-9、A-ZからI、L、O、Uを除く)はすべてURL unreserved文字のため、パーセントエンコーディングは不要です。

Q: 生成したULIDの衝突確率はどのくらいですか?

A: 80ビットのランダム成分を持つため、1秒間に100万個のULIDを生成し続けたとしても、衝突が発生するまでに約1兆秒(約3万2千年)かかる計算になります。実用上、衝突を心配する必要はまずありません。