UUID、ULID、SQID、Snowflake IDのユニークIDの選び方

## **はじめに**

[CYBIRD Advent Calendar 2024](https://qiita.com/advent-calendar/2024/cybird)の最終日担当の@dave_cです。
24日目は@cy-seiyanさんの「[MacでブータブルUSBの作成に挑戦した話](https://qiita.com/cy-seiyan/items/3e86bc5e7289559ecdcd)」でした。

---

## **概要**

システム設計において、データやエンティティを一意に識別するためのIDは非常に重要です。適切なIDの選択は、システムのパフォーマンスやスケーラビリティ、セキュリティに大きな影響を与えます。本記事では、以下の4つのID方式について比較・解説します。

- **UUID (Universally Unique Identifier)**  
- **ULID (Universally Lexicographically Sortable Identifier)**  
- **SQID (Sequential ID)**  
- **Snowflake ID**

---

## **UUID**

### **概要**
UUIDは、128ビットの一意な識別子です。主に以下のバージョンが使われます。
- **UUIDv1**: タイムスタンプとMACアドレスを組み合わせた方式
- **UUIDv4**: ランダム値を使用して生成

### **特徴**
- **ユニーク性**: グローバルに一意で、複数のシステム間で競合しません。
- **汎用性**: 多くのプログラミング言語やデータベースで標準サポートされています。
- **順序性**: UUIDv4はランダム値で順序性はありませんが、UUIDv1はタイムスタンプを含むため部分的な順序性を持ちます。

### **利点**
1. **標準化**: 多くのシステムやツールと互換性があります。
2. **設定不要**: 中央管理なしで生成可能。

### **欠点**
1. **サイズ**: 128ビットの長さがストレージやインデックスに負担をかけます。
2. **可読性**: 人間にとっては理解しづらい長い形式（例：`550e8400-e29b-41d4-a716-446655440000`）。
3. **性能**: 順序性がないため、データベースでのインデックス性能が劣る場合があります。

---

## **ULID**

### **概要**
ULIDは、UUIDと同様に128ビットですが、タイムスタンプとランダム値を組み合わせることで、ソート可能な特性を持つ識別子です。Base32でエンコードされており、人間が比較的読みやすい形式になります。

### **特徴**
- **ソート可能**: タイムスタンプに基づくため、時間順に並べ替えが可能。
- **ユニーク性**: ランダム値部分により衝突を防ぎます。
- **可読性**: Base32により、UUIDより短く人間に優しい（例：`01F8MECHZX3TBDSZ7A3Q2T8YZM`）。

### **利点**
1. **順序性**: タイムスタンプでのソートが容易。
2. **ユニーク性**: 分散システムでも安全に利用可能。
3. **可読性**: UUIDよりも短く扱いやすい。

### **欠点**
1. **ライブラリ依存**: UUIDほど広く標準化されておらず、生成に専用ライブラリが必要。
2. **ストレージサイズ**: UUIDと同様に128ビットでやや大きい。

---

## **SQID**

### **概要**
SQIDは、シンプルな連番IDです。データベースのオートインクリメント機能やカウンターを用いて生成されます。

### **特徴**
- **順序性**: 完全に連続した順序を持つため、挿入順が明確。
- **ユニーク性**: 単一のデータベース内でユニーク。

### **利点**
1. **簡単**: 実装が非常に容易。
2. **順序性**: 完全な時間順を保証。
3. **コンパクト**: 小さなサイズ（4〜8バイト）で効率的。

### **欠点**
1. **スケーラビリティ**: 分散システムでは利用が困難。
2. **予測可能性**: 次のIDが簡単に予測可能で、セキュリティリスクになり得る。
3. **ボトルネック**: 高並列性環境で競合が発生しやすい。

---

## **Snowflake ID**

### **概要**
Snowflake IDはTwitterが開発した分散ID生成アルゴリズムで、64ビットの識別子を生成します。以下の要素で構成されます。
- **タイムスタンプ**: ミリ秒単位での生成時刻。
- **マシンID**: 分散環境での一意性を保証。
- **シーケンス番号**: 同一ミリ秒内の衝突回避。

### **特徴**
- **ユニーク性**: 分散システム間での一意性を保証。
- **順序性**: 時間に基づくおおよその順序性。

### **利点**
1. **スケーラビリティ**: 高並列性環境に対応。
2. **効率性**: 中央管理なしでの高速生成。
3. **順序性**: 時間順に近い順序性を持つ。

### **欠点**
1. **複雑性**: 実装がやや難しく、設定ミスで衝突のリスク。
2. **サイズ制限**: 64ビットであるため、極端に長期間の運用には非適切。

---

## **比較表**

| 特徴               | UUID                | ULID                 | SQID                  | Snowflake ID          |
|--------------------|---------------------|----------------------|-----------------------|-----------------------|
| **ユニーク性**     | グローバルに一意    | グローバルに一意     | 単一インスタンスで一意 | グローバルに一意      |
| **順序性**         | 無（v4）            | 時間順にソート可能   | 完全な順序性          | 時間順（近似）        |
| **スケーラビリティ**| 高い                | 高い                 | 低い                  | 高い                  |
| **可読性**         | 低い                | 中程度               | 高い                  | 中程度               |
| **サイズ**         | 128ビット           | 128ビット            | 小さい（4〜8バイト）   | 64ビット             |
| **用途**           | 分散システム全般    | 時間順が必要な分散システム | シンプルなアプリ      | 高並列な分散システム |

---

## **まとめ**

### **利用シーンに応じた選択**
- **シンプルなデータベース**: **SQID**  
- **高スケーラビリティが必要な分散システム**: **Snowflake ID**  
- **標準化された環境や相互運用性が重要**: **UUID**  
- **時間順ソートや読みやすさが必要**: **ULID**

ID方式の選択は、システムの規模、性能要件、データ特性に応じて慎重に行いましょう。

## **最後に**

今年も[CYBIRD Advent Calendar 2024](https://qiita.com/advent-calendar/2024/cybird)ご覧いただき、ありがとうございました！2024年、お疲れ様でした！