システム開発をしていると、こんな文字列をよく見かけます。
a3f1b2c4-7e8d-4f2a-9b1c-0e5d3f6a2b8c
これは UUID(Universally Unique IDentifier) です。データベースの主キー、APIのリクエストID、セッション管理など、「世界中で一意なID」が必要な場面で使われます。
この記事では、Lapis Tech Toolsの UUID/ULIDジェネレーター を題材に、UUIDの仕組みと実装を解説します。
1. なぜ連番IDではダメなのか
データベースの主キーに「1, 2, 3…」という連番を使う方法もあります。ではなぜUUIDが使われるのでしょうか?
| 問題 | 連番ID | UUID |
|---|---|---|
| 複数のサーバーで同時に生成 | 衝突する(調整が必要) | 衝突しない(独立生成可能) |
| IDから件数が推測される | id=100 なら100件だとわかる | 推測不可能 |
| テーブルのマージ(データ統合) | IDが重複する | 重複しない |
| 削除後に再利用される可能性 | 古いURLが別のリソースを指す | 削除したIDは二度と使われない |
マイクロサービス構成やデータ統合が多い現代のWebシステムでは、UUIDのほうが適しているケースが多くなっています。
2. UUIDの構造:32桁の16進数
UUID は 128ビット(32桁の16進数) を、5グループのハイフン区切りで表現します。
a3f1b2c4-7e8d-4f2a-9b1c-0e5d3f6a2b8c
├───────┘ └──┘ └──┘ └──┘ └──────────┘
8桁 4桁 4桁 4桁 12桁
UUID v4 の場合、ほぼすべてのビットがランダムです(2ビットだけバージョン識別子が入ります)。
xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
↑ ↑
バージョン4を示す バリアント識別子
3. なぜ衝突しないのか
UUID v4 は 128ビットのうち 122ビットがランダムです。取りうるパターン数は:
2^122 = 約 5.3 × 10^36(5澗)
1秒間に10億個生成し続けても衝突が起きる確率は、100年後でも天文学的に低い数字です(ビッグバン以降の宇宙の年齢より長い時間が必要)。
実務的には「衝突は起きない」と扱って問題ありません。データベースのUNIQUE制約を念のため付けておけば万全です。
4. JavaScriptでの生成方法
現代のブラウザ(推奨)
// Web Crypto API(ブラウザ・Node.js 14.17+対応)
const uuid = crypto.randomUUID();
console.log(uuid);
// → 'a3f1b2c4-7e8d-4f2a-9b1c-0e5d3f6a2b8c'
crypto.randomUUID() はブラウザの暗号論的乱数生成器(CSPRNG)を使うため、Math.random() よりはるかに安全です。
自前実装(仕組みを理解したい場合)
function generateUUIDv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
(c) => {
const r = (Math.random() * 16) | 0;
// y は 8,9,a,b のどれか(バリアント識別子)
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
}
);
}
テンプレート文字列の各 x をランダムな16進数に、y をバリアント識別子のルールに従って置換しています。
5. ULIDとは何か:UUIDの弱点を補う
UUIDにはひとつ弱点があります。完全ランダムのため、時間順でソートできないことです。
データベースに大量のUUIDを主キーとして挿入すると、インデックスがランダムな位置に分散し、書き込みパフォーマンスが低下します(Bツリーインデックスの断片化)。
ULID(Universally Unique Lexicographically Sortable Identifier) はこの問題を解決します。
01HXYZ123456789ABCDEFGHIJK
├──────────┘ └────────────┘
タイムスタンプ(48bit) ランダム(80bit)
| 比較 | UUID v4 | ULID |
|---|---|---|
| ソート可能 | ✗(完全ランダム) | ✓(時間順) |
| 衝突耐性 | 122bit のランダム | 80bit のランダム |
| 文字数 | 36文字(ハイフン含む) | 26文字 |
| 大文字・小文字 | 16進数のみ | Base32(A-Z, 0-9) |
| DB書き込み速度 | 遅くなりやすい | 速い(インデックス断片化なし) |
ULIDの生成(JavaScriptライブラリ)
// ulidライブラリを使う場合
import { ulid } from 'ulid';
const id = ulid();
console.log(id);
// → '01HXYZ1234567890ABCDEFGH'
// 時間順でソートすると自動的に生成順になる
const ids = [ulid(), ulid(), ulid()];
console.log(ids.sort()); // 生成順と一致
6. 複数件を一括生成する仕組み
Lapis Tech ToolsのUUIDジェネレーターでは1〜100件を一括生成できます。
function generateMultiple(type, count) {
const results = [];
for (let i = 0; i < count; i++) {
if (type === 'uuid') {
results.push(crypto.randomUUID());
} else {
// ULID生成ロジック
const timestamp = Date.now(); // 現在時刻(ミリ秒)
results.push(encodeULID(timestamp));
}
}
return results.join('\n');
}
同一ミリ秒内に複数のULIDを生成する場合、ランダム部分を1ずつインクリメントして順序を保証する実装が標準的です(ULIDの仕様で定義されています)。
7. 実務でのUUID活用例
APIのべき等性(Idempotency Key)
// 支払いAPIに同じリクエストを2回送っても二重課金しないための仕組み
const response = await fetch('/api/payments', {
method: 'POST',
headers: {
'Idempotency-Key': crypto.randomUUID(), // 同じキーなら同じ結果を返す
'Content-Type': 'application/json',
},
body: JSON.stringify({ amount: 1000, currency: 'JPY' }),
});
ファイルアップロードの一意名
// ユーザーが「image.jpg」をアップロードしても衝突しない
async function uploadFile(file) {
const uniqueName = `${crypto.randomUUID()}.${file.name.split('.').pop()}`;
// → 'a3f1b2c4-7e8d-4f2a-9b1c-0e5d3f6a2b8c.jpg'
}
8. まとめ
| 学んだこと | 内容 |
|---|---|
| UUID v4 | 128bit(122bitランダム)の一意識別子。実用上衝突しない |
| 構造 | 32桁16進数をハイフンで5グループに分けた xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx |
| JS生成 | crypto.randomUUID() が最も安全・簡単 |
| ULID | タイムスタンプ+ランダムで時間順ソート可能。DB書き込みが速い |
| 用途 | DB主キー・APIリクエストID・ファイル名・べき等性キー |
一度UUIDを使い始めると、連番IDには戻れなくなります。UUIDジェネレーターでコピーしてすぐに使ってください。
ツール解説シリーズ:第1回・IP計算機 | 第2回・Base64エンコーダー | 第3回・chmod計算機 | 第4回・JSONフォーマッター | 第5回・Cronジェネレーター | 第6回・正規表現テスター | 今ここ(第7回・UUIDジェネレーター) | 第8回・Markdownプレビュー
関連記事
CHECK IT OUT
サブスク加入者限定の
コンテンツを配信中
- 毎月のAI・自動化トレンドレポート
- クリエイター向け業務効率化テンプレート
- ツール選定・SaaS比較まとめ(限定公開)
「これ自動化できないかな?」
そのアイデア、ITで実現できます。
業務の自動化・お客様向けツール開発・AI活用まで、クリエイター・個人事業主専門のITコンサルタントが対応します。まずは気軽にご相談ください。