💠

【DB】id を作成する際に意識した3つのチェックポイントと、文字列 id は ULID or UUID v7 がおすすめという話

2024/05/12に公開

こんにちは、Webエンジニアのまさぴょんです!
今回は、id を作成する際に意識した3つのチェックポイントと、文字列 id は ULID or UUID v7がおすすめという話について、解説します🐱

結論・まとめ

要点だけ、知りたい人向けに、調査結果をまとめると、次のような内容になります。

3つのチェックポイントの調査結果

  1. id の命名は、user_idtask_idのようにid名を具体化したが方が、明確であり可読性が上がる👀
  2. id のデータ型は、柔軟性・拡張性が高い文字列型がおすすめ🌟
    • 数値型の表現できる幅・フォーマットは、文字列型に比べて少ない
    • 文字列型の方が柔軟性が高く、拡張・変更が容易
  3. 文字列の id データの生成をするなら、ULID or UUID v7がおすすめ🌟
    • 実装難易度が低い
    • UUID v4 はソート不能だが、ULID or UUID v7はソート可能な ID を生成できる
      • タイムスタンプが文字列ID内に含まれるので、ソート可能となる
    • UUID v4 だと、DBのパフォーマンスが低くなる問題をULID or UUID v7なら回避できる

1. idの命名について

まずは、1つ目のチェックポイントは「idの命名について」です👀

Q: id は user_id のように名前を具体化するべきか?

A: user_idのように具体化した方が、明確であり可読性が上がる

一般的には、より具体的なid名を使用する方が、他のidとの識別性・可読性が上がるため、user_idtask_idのように、id名を具体化することをお勧めします。

2. idのデータ型について

続いて、2つ目のチェックポイントは「idのデータ型について」です👀

Q: id は、数値型にすべきか、文字列型にすべきか?

A: id のデータ型は、柔軟性・拡張性が高い文字列型がおすすめ🌟

id のデータ型は、柔軟性・拡張性が高い文字列型が、個人的におすすめです🌟
おすすめの理由は、次のとおり👀

  1. 数値型の表現できる幅・フォーマットは、文字列型に比べて少ない
  2. 数値型だと、組み合わせの数が少ないため、IDの推測容易性が高い(セキュリティリスクが高い)
  3. 文字列型の方が柔軟性が高く、フォーマットなどの拡張・変更が容易

3. id を文字列型で生成する場合のフォーマットについて

最後に、3つ目のチェックポイントは「id を文字列型で生成する場合のフォーマットについて」です👀

Q: id生成の種類・フォーマットは、どんなものがいいのか?

A: 文字列の id データの生成をするなら、ULID がおすすめ🌟

結論から言うと、文字列の id データの生成をするなら、ULID が個人的におすすめです。
判断理由の材料として、Auto Increment, UUID v4, ULID, Snowflake, UUID v7 の5つの規格・フォーマットを比較している比較表を引用します。
こちらの比較表を見て、

  1. DBのパフォーマンスを、なるべく損なわない
  2. IDの推測容易性が低い(セキュリティリスクが低い)
  3. 実装難易度が低い
    をバランスよく満たしてくれる ULID or UUID v7がおすすめという結論になりました🧐
機能項目 Auto Increment UUID v4 ULID Snowflake UUID v7
IDのサイズ 4–8 byte 16 byte 16 byte 8 byte 16 byte
IDの衝突確率 高い 極めて低い 極めて低い 最高 極めて低い
ID生成の依存性 データベース依存 環境依存なし 環境依存なし 環境依存〜不依存 環境依存なし
分散サポート 低い 高い 高い 高い 高い
レコード挿入パフォーマンス 高い 低い
IDの推測容易性 (セキュリティ上の問題性) 低い 高い
実装の複雑さ 低い 低い 低い 中〜高 低い
ソート可能性 高い 低い 高い 高い 高い
時間情報の有無 なし なし あり あり あり

引用元: 他のレコードと違う存在になりたいレコードへ

各・規格に関する詳細は、引用記事にて、ご確認ください🙏
https://zenn.dev/mbao/articles/db-record-identifier

JavaScriptで ULID を生成する実装方法

各プログラミング言語ごとに、ULIDを生成するためのライブラリなどが展開されていると思います。
JavaScriptの場合は、ulidというライブラリがあるので、それを利用すれば、ULIDが生成できます🌟

https://www.npmjs.com/package/uuid

npm install --save ulid
import { ulid } from "ulid";

ulid(); // 01ARZ3NDEKTSV4RRFFQ69G5FAV

// seed timeを指定する場合
ulid(1469918176385); // 01ARYZ6S41TSV4RRFFQ69G5FAV

JavaScriptで UUID v7 を生成する実装方法

UUID v7は、最近サポートされてきた新しい形式ですが、
各プログラミング言語ごとに、UUID v7を生成するためのライブラリなどが展開されていると思います。
JavaScriptの場合は、ui7というライブラリがあるので、それを利用すれば、ULIDが生成できます🌟

https://www.npmjs.com/package/ui7

npm install --save ui7
import uuid, { timestamp } from "ui7";

// UUID v7
const id = uuid();
// ==> "01836531-a895-7a2d-a70d-504ea62b40e2"

// idから日付取得
const when = new Date(timestamp(id));
// ==> 2022-09-22T12:34:56.789Z

【おまけ】 UUID v4 は、Web標準で簡単に実装できる

UUID v4 を作成するには、Web標準技術のcrypto.randomUUID()を使います。
実行結果(返り値)は、ランダムに生成された 36 文字長の v4 UUID を含む文字列です。

// UUID を作成する
const uuid = crypto.randomUUID();
console.log(uuid);

MDN: Crypto: randomUUID() method を見てもらえば、わかりますが、すべてのBrowserでサポートされており、Node.jsでも使用することができます。
ただし、バージョンなどには注意です。

Nodeのバージョンが低いなど、環境的に使えない場合は、uuid ライブラリがあります。
https://www.npmjs.com/package/uuid

まとめ・感想

Xやっております!よかったらフォローしてください🐱
https://twitter.com/masanyon1212

参考・引用

https://zenn.dev/j5ik2o/articles/a085ab3e3d0f197f6559

https://qiita.com/sato-shin/items/0ec486d9c1bf98d9bf4c

https://zenn.dev/mbao/articles/db-record-identifier

https://kakehashi-dev.hatenablog.com/entry/2021/12/12/080000

https://qiita.com/kai_kou/items/b4ac2d316920e08ac75a

https://qiita.com/He3-toolbox/items/08976418b207b813c442

https://www.memory-lovers.blog/entry/2022/02/28/111059

https://github.com/ulid/javascript

https://masanyon.com/javascript-randam-uuid-create/

https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID

https://www.npmjs.com/package/uuid

Discussion