ハッシュ・ID・乱数
UUIDに日時が入っている?v4とv7を見比べたい
使うツール
UUIDを使えば一意になりそうだけれど、v4とv7のどちらを選べばよいのでしょう。文字列の長さは同じでも、ランダム性を中心にしたv4と、先頭に時刻を含むv7では、並べたときに見える情報が違います。SheepDevのUUID生成・確認で少数を作り、既知の例を解析しながら、その違いを見てみます。データベースの速度や認証の安全性をこの画面だけで決めるのではなく、IDへ何を期待するかを整理するための実験です。
見た目のハイフンより、版の数字を見る
xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx (v4)
xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx (v7)UUIDは128ビットで、一般的な表記では32桁の16進数をハイフンで区切ります。三つ目のまとまりの先頭が版を示す位置です。ただし、この図は位置の説明で、xやyを含む文字列を有効なUUIDとして入力する例ではありません。長さとハイフンが合うだけでは、ツールの形式確認に通るとは限りません。
生成したUUIDを一つコピーして入力欄へ戻すと、このツールは生成件数ではなく解析するUUIDとして扱います。結果のversionとvariantを確認します。複数行をまとめて入力する一括検証ではないため、解析の実験は一つずつ行います。生成時に使った版と、解析された版が一致することを最初の確認にします。
v4を並べても、作った順番にはならない
件数を5、版をv4にして生成し、結果を行の整理ツールへ渡して並べ替えてみます。v4にはこの用途の生成時刻フィールドがないため、文字順は作った順を表しません。たまたま同じ順に見えても、時刻を読めたわけではありません。時系列で並べたいデータには、別の作成日時や、順序を定義する項目が必要かを検討します。
ランダムなIDは、連番のように次の値が見えやすい方式とは違いますが、IDを知っているだけで閲覧できる設計を安全にするものではありません。公開IDとアクセス権限の確認は分けます。また、テストで数個が重複しなかったことだけを、一意性が数学的に保証された証拠として扱いません。
v7には、ミリ秒単位の時刻が入る
017f22e2-79b0-7cc3-98c4-dc0c0c07398f
1645557742000 ms
2022-02-22T19:22:22.000ZこのUUIDを入力すると、versionは7で、先頭に入ったUnixミリ秒1645557742000とUTC時刻を確認できます。v7は先頭48ビットへUnixミリ秒を置く構造なので、時刻が異なる値の通常の表記を並べると、時刻部分が並びに反映されます。v4のように全体の順序が時刻と無関係な場合との違いを、同じ解析画面で確認できます。
時刻を読めることは、生成した人や正しい時計で作られたことの証明ではありません。この例も公開された固定値です。文字列をコピーしたり、時刻部分を持つ値を別の処理で作ったりできるため、解析結果は参考時刻として扱います。利用者へ公開するIDなら、時刻情報を見せることが用途に合うかも確認します。
同じミリ秒と、別の生成元の順序には注意する
同じミリ秒に複数作ったときの順序は、残りのビットの作り方や生成器の状態管理に関係します。SheepDevは採用しているuuidライブラリで生成していますが、この画面の生成順を、別端末・別プロセス・再起動をまたぐ全世界共通の順序として保証するものではありません。時計のずれもあるため、重要なイベント順序をIDだけで確定しないでください。
また、データベースのUUID型や独自のバイナリ保存では、文字列と同じ順に比較されるかを確認します。文字列を行ソートして期待どおりだったことだけで、データベースのインデックスや並べ替えも同じ結果だと決めません。保存形式、比較規則、実際の問い合わせを小さなデータで照合する必要があります。
v7だからDBが必ず速くなる、とは結論しない
時刻順の性質が保存や検索の設計に役立つ場合はありますが、性能はインデックス、データ量、書込み方法、問い合わせによって変わります。このUUIDツールはDBへ接続せず、性能測定もしません。選択理由として『時刻部分を持つIDが必要』『時刻を表さないランダムな識別子が必要』と要件を先に書き、性能を理由にするなら実際の環境で検証します。
共有する確認結果には、版、形式確認の結果、v7なら参考時刻、生成と解析のどちらを行ったかを残します。『有効な形式』を『信頼できる値』と呼び替えず、実データの一意性や権限の検証は別に維持します。少数の生成実験で分かる性質と、運用で保証すべきことを分ければ、v4とv7を見た目の流行だけで選ばずに済みます。