UUID:自動インクリメントが十分でない時
一意識別子が重要な理由と、連番IDの代わりにいつ使うべきか。
データベースが自動インクリメントIDを使っています。1, 2, 3, 4... シンプル。
それから2つのデータベースをマージ。あるいはURLでIDを公開。あるいは誰かがURLのIDをインクリメントして他のユーザーのデータを推測できることに気づきます。
連番IDには問題があります。UUIDがそれらのいくつかを解決します。
UUIDって何?
Universally Unique Identifier。128ビットの数値で、通常はダッシュ付きの32文字の16進数として表示:
550e8400-e29b-41d4-a716-446655440000
UUID生成の背後にある数学が衝突を天文学的にありえなくします。調整なしに、異なるマシンで、異なる時間にUUIDを生成でき、衝突しません。
なぜ自動インクリメントだけを使わないのか?
セキュリティ。 連番IDは情報を漏らします。ユーザーIDが15847なら、攻撃者は少なくとも15846人の他のユーザーがいることを知ります。連番IDを試してリソースを列挙できます。
分散システム。 複数のサーバーがIDを生成するには重複を避けるための調整が必要。UUIDには調整不要。
データのマージ。 連番IDのデータベースを結合するのは悪夢。UUIDはきれいにマージ。
オフライン作成。 モバイルアプリはUUIDでオフラインでレコードを作成できます。サーバー割り当てIDを待つ必要なし。
UUIDバージョン
すべてのUUIDが同じ方法で作られるわけではありません。
バージョン1: タイムスタンプとMACアドレスに基づく。一意ですが、いつどこで作られたかを明らかにします。
バージョン4: ランダム。最も一般的。情報漏洩なし。
バージョン7: タイムスタンプベースだがソート可能。新しいデータベースが恩恵を受けます。
ほとんどの用途では、バージョン4(ランダム)が正しい選択。
トレードオフ
UUIDは無料ではありません。
サイズ。 整数の32ビットに対して128ビット。より大きなインデックス、より多くのストレージ。
可読性。 user/15 は user/550e8400-e29b-41d4-a716-446655440000 より覚えやすい。
パフォーマンス。 ランダムUUIDは一部のデータベースでインデックスフラグメンテーションを引き起こします。UUID v7がこれに対処。
デバッグ。 ログでUUIDを検索するのは単純な数字と比べて退屈。
いつ何を使うか
自動インクリメントを使う時:
- 内部のみ、ユーザーに公開されない
- シンプルなアプリケーション、単一データベース
- 人間の可読性が重要
UUIDを使う時:
- IDがURLやAPIに現れる
- 複数のシステムがレコードを作成
- 不明瞭性によるセキュリティが助けになる
- データのマージが可能
実践的なコツ
MySQLでUUIDをプライマリキーとして使わない。 代わりにセカンダリのユニークカラムとして使いましょう。MySQLのクラスタ化インデックスはランダムUUIDでパフォーマンスが悪い。
UUID v7を検討。 データベースがサポートしているなら、タイムスタンプソート可能なUUIDが両方の良いとこ取りを提供。
URLではダッシュを削除。 550e8400e29b41d4a716446655440000 はまだ有効なUUIDでURLで短い。
UUIDは連番IDができない実際の問題を解決します。でも常に正しい選択ではありません。UUIDがよりプロフェッショナルに聞こえるからではなく、実際の要件に基づいて選びましょう。