UUIDとは何ですか?なぜそれらが役立つのですか?

ここに画像の説明を挿入
Universally Unique Identifier(UUID)は、ほとんどの実用的な目的で一意であると安全に見なすことができる特定の形式の識別子です。2つの異なる環境で異なるパーティによって作成された場合でも、正しく生成された2つのUUIDが同じである可能性はほとんどありません。そのため、UUIDは普遍的に一意であると言われています。

この記事では、UUIDの特性、その一意性がどのように機能するか、およびUUIDがリソースの識別を簡素化できるシナリオについて学習します。データベースレコードと相互作用するソフトウェアの一般的な観点からUUIDにアプローチしますが、分散型の一意のIDの生成を必要とするすべてのユースケースに広く適用できます。

UUIDとは正確には何ですか?

UUIDは単なる値であり、一意の値として安全に扱うことができます。衝突のリスクは非常に低いため、完全に無視することを合理的に選択できます。異なる用語(GUIDまたはグローバル一意識別子、Microsoftの推奨セマンティクス)を使用して参照されているUUIDが表示される場合がありますが、意味と効果は同じです。

真のUUIDは、標準化された形式で生成および表現される一意の識別子です。有効なUUIDはRFC4122で定義されています。この仕様では、中央の発行機関を必要とせずに、実装間で一意のままのUUIDを生成するために使用できるアルゴリズムについて説明しています。

RFCには、5つの異なるアルゴリズムが含まれており、それぞれが異なるメカニズムを使用して値を生成します。利用可能な「バージョン」の概要は次のとおりです。

  • バージョン1-時間ベース-タイムスタンプ、クロックシーケンス、および生成デバイスに固有の値(通常はそのMACアドレス)を組み合わせて、その時点でそのホストの一意の出力を生成します。
  • バージョン2-DCEセキュリティ-このバージョンは、分散コンピューティング環境(DCE)で使用するためのバージョン1の進化形として開発されました。広く使われていません。
  • バージョン3-名前ベース(MD5)
    -MD5は、「名前空間」と「名前」をハッシュして、名前空間内で一意の値を作成します。同じ名前空間と名前で別のUUIDを
    生成すると同じ出力が生成されるため、このメソッドは再現性のある結果を提供します。
  • バージョン4-ランダム-最近のほとんどのシステムは、ホストの乱数のソースを使用してその値を公開するため、UUIDv4を選択する傾向があります。同じUUIDを2回生成する可能性
    はほとんどありません。
  • バージョン5-名前ベース(SHA-1)-これはバージョン3に似ていますが、より強力なSHA-1アルゴリズムを使用して入力名前空間と名前をハッシュします。
    RFCはアルゴリズムをバージョンとして参照していますが、最新のように見えるため、常にバージョン5を使用する必要があるという意味ではありません。どちらを選択するかはユースケースによって異なります。多くの場合、v4はランダム性のために選択されます。これにより、単純な「新しい識別子を教えてください」シナリオに最適です。

生成アルゴリズムは、128ビットの符号なし整数を出力します。ただし、UUIDはより一般的には16進文字列であり、16文字のバイナリシーケンスとして格納することもできます。UUID文字列の例を次に示します。

16763be4-6022-406e-a950-fcd5018633ca

値は、ダッシュ文字で区切られた5組の英数字として表されます。ダッシュは文字列の必須コンポーネントではありません。ダッシュの存在は、UUID仕様の履歴の詳細によって異なります。また、識別子を人間の目に認識しやすくします。

UUID 用例

UUIDの主な使用例は、一意の識別子の分散型生成です。UUIDはどこからでも生成でき、バックエンドコード、クライアントデバイス、データベースエンジンのいずれからのものであっても、安全に一意であると見なすことができます。

UUIDは、切断された環境でのオブジェクトIDの決定と維持を簡素化します。歴史的に、ほとんどのアプリケーションは主キーとして自動インクリメント整数フィールドを使用していました。新しいオブジェクトを作成するとき、データベースに挿入されるまでそのIDはわかりません。UUIDを使用すると、アプリケーションの早い段階で自分自身を識別できます。

これは、違いを示す基本的なPHPデモです。まず、整数ベースのシステムを見てみましょう。

class BlogPost { 
    public  function __construct ( 
        public readonly ?int $Id , 
        public readonly string $Headline , 
        public readonly ?AuthorCollection $Authors = null )  { } 
}
 
#[POST("/posts")]
 function createBlogPost ( HttpRequest $Request )  : void { 
    $headline  =  $Request  ->  getField ( "Headline" ) ; 
    $blogPost  =  new BlogPost ( null ,  $headline ) ; 
}

データベースに永続化されるまで実際のIDがわからないため、Idプロパティを初期化する必要があります。これは理想的ではありません。実際にはnull許容であってはならず、インスタンスが不完全な状態で存在することを許可します。Idプロパティ。nullなので、データベースに永続化されるまで実際のIDを知ることはできません。これは理想的ではありません。実際にはnull許容であってはならず、インスタンスが不完全な状態で存在することを許可します。Idプロパティこれデータベース永続れるまで実際IDわからないためです。__ _ _ _ _ これ理想的はありませ-実際にはnull許容あってはならずインスタンスがnull許容ならないようにします完全な状態が存在しますIdBlogPost

UUIDに変更すると、問題が解決しました。

class BlogPost { 
    public  function __construct ( 
        public readonly string $Uuid , 
        public readonly string $Headline , 
        public readonly ?AuthorCollection $Authors = null )  { } 
}
 
#[POST("/posts")]
 function createBlogPost ( HttpRequest $Request )  : void { 
    $headline  =  $Request  ->  getField ( "Headline" ) ; 
    $blogPost  =  new BlogPost ( "16763be4-..." ,  $headline ) ; 
}

重複する値のリスクを冒すことなく、アプリで投稿IDを生成できるようになりました。これにより、オブジェクトインスタンスが常に有効な状態を表し、厄介なnull許容IDプロパティを必要としないことが保証されます。このモデルは、トランザクションロジックの処理も簡単です。親を参照する必要のある子レコード(Postの作成者の関連付けなど)は、親に割り当てられたIDを取得するためのデータベースラウンドトリップを必要とせずに、すぐに挿入できます。

将来的には、ブログアプリケーションがより多くのロジックをクライアントに移動する可能性があります。おそらく、フロントエンドは完全にオフラインのドラフト作成のサポートを獲得し、ユーザーのデバイスに一時的に保存されるBlogPostのインスタンスを効果的に作成しました。これで、クライアントは投稿のUUIDを生成し、ネットワークに再接続するときにサーバーに送信できます。その後、クライアントがサーバーのドラフトコピーを取得すると、UUIDがすでにわかっているため、残りのローカル状態と照合できます。

UUIDは、さまざまなソースからのデータを組み合わせるのにも役立ちます。整数キーを使用するデータベーステーブルとキャッシュを組み合わせるのは、面倒でエラーが発生しやすい場合があります。UUIDは、テーブル内だけでなく、ユニバースレベル全体でも一意性を提供します。これにより、異なるストレージシステム間で頻繁に移動される複製された構造やデータの候補として適しています。

UUIDがデータベースに遭遇したときの考慮事項

UUIDの利点は魅力的です。ただし、実際のシステムで使用する場合は、いくつかの問題に注意する必要があります。整数IDをサポートする大きな要因は、整数IDの拡張と最適化が容易なことです。データベースエンジンは、数値のリストを一方向にのみ簡単にインデックス付け、並べ替え、およびフィルタリングできます。

UUIDについても同じことは言えません。まず、UUIDは整数の4倍の大きさです(36バイト対4バイト)。大きなデータセットの場合、これ自体が重要な考慮事項になる可能性があります。これらの値の並べ替えとインデックス付けも、特にランダムUUIDの最も一般的なケースでは注意が必要です。それらのランダム性は、それらに自然な秩序がないことを意味します。これは、主キーとしてUUIDを使用する場合、インデックス作成のパフォーマンスを低下させます。

これらの問題は、外部キーを多用する正規化されたデータベースで悪化する可能性があります。これで、多くのリレーショナルテーブルが作成され、それぞれに36バイトのUUIDへの参照が含まれる場合があります。最終的に、結合とソートを実行するために必要な追加のメモリは、システムパフォーマンスに大きな影響を与える可能性があります。

UUIDをバイナリデータとして保存することで、これらの問題を部分的に軽減できます。これは、VARCHAR(36)ではなくBINARY(16)列を意味します。一部のデータベース(PostgreSQLなど)には組み込みのUUIDデータ型が含まれています。MySQLなどの他の関数は、UUID文字列をそのバイナリ表現に変換できます。この方法の方が効率的ですが、データの保存と選択に追加のリソースを使用することに注意してください。

効果的な戦略は、整数を主キーとして保持することですが、アプリケーション参照用にUUIDフィールドを追加します。コードでUUIDを使用してトップレベルのオブジェクトを取得および挿入する場合、リレーショナルリンクテーブルはIDを使用してパフォーマンスを向上させることができます。それはすべて、システム、そのサイズ、および優先順位によって異なります。分散IDの生成と直接データのマージが必要な場合は、UUIDが最適ですが、トレードオフが必要です。

一般化する

UUIDは、分散型IDの生成に安全に使用できる一意の値です。衝突が発生する可能性はありますが、考慮から除外できるほどまれである必要があります。1世紀全体で1秒あたり10億のUUIDを生成する場合、十分なエントロピーが利用可能であると仮定すると、重複に遭遇する確率は約50%です。

挿入が行われる前に、UUIDを使用してデータベースに依存しないIDを確立できます。これにより、アプリケーションレベルのコードが簡素化され、誤って認識されたオブジェクトがシステムに存在するのを防ぎます。テーブルレベルで動作する従来の整数キーとは異なり、UUIDは、データストア、デバイス、または環境に依存しない一意性を保証することにより、データレプリケーションも支援します。

UUIDは現在、ソフトウェア開発に広く普及していますが、完全なソリューションではありません。初心者は競合の可能性に焦点を合わせる傾向がありますが、システムが非常に敏感で一意性を保証する必要がない限り、これを主な考慮事項にするべきではありません。
ほとんどの開発者にとってより明白な課題は、生成されたUUIDの保存と取得です。VARCHAR(36)を単純に使用する(またはハイフンを削除してVARCHAR(32)を使用する)と、ほとんどのデータベースインデックスの最適化が無効になるため、時間の経過とともにアプリケーションが機能しなくなる可能性があります。データベースシステムの組み込みUUID処理を調査して、ソリューションから最高のパフォーマンスを引き出すようにします。

おすすめ

転載: blog.csdn.net/wlcs_6305/article/details/123294632