web-dev-qa-db-ja.com

自動インクリメントIDに加えてUUIDを使用する

新しいプロジェクトのDBスキーマを設計しようとしています。いくつかの提案が必要です。一部のテーブルにはUUIDである1つの追加の列があると考えています。私は主にRESTを介してアクセス可能なデータを含むテーブルを望んでいたので、主キーを公開したくありません。私の懸念は、テーブルを更新するときに、元の主キーを取得するためだけにもう1つクエリを実行する必要があることです。

どう思いますか?

7
pik4

アプリケーションを設計する際の最大の神話は、1つのキーしか持てないということです。

複数のキーを用意し、先に進んでください。アプリケーションは、データベースとは異なる主キーを持つことができます。これは最初は奇妙に聞こえるかもしれませんが、あなたはこのルートに行く両方の世界のベストを手に入れます。

UUIDには多くの利点がありますが、一般に恐ろしいクラスター化インデックスを作成します。そのため、DBでPK /クラスター化インデックスとしてintを使用するだけで、外部ID列に別の一意のインデックスを設定することもできます。これは、多くのクエリに追加の結合を必要とする場合がありますが、リレーショナルDBでは、自動インクリメントされたint列の内部結合が非常に高速であるため、問題ありません。

このデュアルキーアプローチのもう1つの利点は、DBを地理的に簡単に分散できることです。 UUIDはグローバルに一意であるため、DB int PKがDBを離れず、残りのサービスで使用されないことを確認する限り、地理的に離れた2つのDBがキーの調整を遅くする必要はありません。

ここでもう1つ、外部IDはUUIDでなくてもかまいません。他のオプションも使用できます。

外部は、int、文字列、またはエンティティの自然キーにすることもできます。何でも。これはあなたのURLをUUIDよりも醜くしません

複数のキーを持つことを恐れないでください。残りのAPIコンシューマーからDBキーを隠すのは良いことです。


これまでに使用したキーのほとんどは2つですが、適切な状況では、最大4つ(DBキー、アプリケーションキー、ビジネスキー、顧客キー)が正当化されることを想像できます。

8
TheCatWhisperer

2つの主キーがあっても意味がありません。

  1. UUIDのインデックス作成は低速です。

いいえそうではありません。ページや断片化のような不可解な数字について心配するのをやめ、いくつかのテストを行います。

https://www.mssqltips.com/sqlservertip/5105/sql-server-performance-comparison-int-versus-guid/

http://byterot.blogspot.com/2013/02/performance-series-guids-vs-identity-rdbms-sql.html

https://www.cybertec-postgresql.com/en/int4-vs-int8-vs-uuid-vs-numeric-performance-on-bigger-joins/

いずれの場合でも、bothがあり、UUIDにインデックスを付けると、同じ問題が発生します

  1. UUIDはより多くのスペースを使用します。はい、そうです、これらの低い最大数のintで問題を回避できる限り。

いずれにしても、bothがある場合、それは間違いなく大きい

  1. UUIDは醜いです。 1つは入力したくないのですが、13243444444431またはGdih£$%d1を入力しますか? SEOやその他の理由できれいなURLが必要な場合は、テーブルにid列を追加するよりも良い解決策があります。

シーケンシャルintには、UUIDで解決されるいくつかの大きな問題があります。そのうちの1つは、次のIDまたは注文した注文数を推測しています。

これらは実際のセキュリティと商業上の問題であり、auto_inc intをまったく使用しないことを正当化するにはそれ自体で十分です。

ハッキーソリューションの問題を修正するのではなく、業界標準に置き換えてください。

5
Ewan

RESTインターフェイスから主キーを非表示にすることが唯一の目標である場合、私はそれに対してアドバイスをします。代わりに、キーを暗号化することは、このための良い解決策です。

これは私が何度も遭遇した共通の問題です。私は「IDに数字を使用する」ルートをたどってしまいました。つまり、クライアントがこれらのUUIDを確認することはそれほど醜いことではありません。

すでにおわかりのように、唯一の別の方法は、そのIDをある種のクエリの背後に隠すことです。正しいUUIDを取得するためにパラメーターをフィードする必要がありますが、これらを使用することもできます。テーブルの主キーとしてのパラメータ!

REST(つまり、モデルの状態転送)を実行する方法はないと思います。RESTしているインスタンスを特定できないため、キーが必要になります。キーがとる形式。

セキュリティが原因で問題が発生している場合は、クライアントがIDを確認するのではなく、サーバーメッセージ検証コードに問題が表示されます。ハッカーがテーブルからデータをロードしたい場合、IDを使用する必要はありません。また、リクエストも検証する必要があるため、メッセージの認証と承認など、とにかくビジネスレイヤーに危険な要素が渡されることはありません。

あなたの質問に戻るには:

「RESTを介してアクセスできるため、主キーを公開したくない」

それは逆だと思います。RESTを行うには、主キーを公開する必要があります。

編集:@マーフが指摘したように、実際にクライアントにIDを指定すると、攻撃者により良い機会が与えられます-私はこれを知りませんでした。ここでの他の答え(私はキーを暗号化するために言っている最も短い答えを見ています)はあなたの状況により正確であるかもしれません。編集2:UUIDはintより安全ではないようです...

1
Dan Rayson

エンティティの公開識別子として主キーを使用する場合の問題は、データストレージソリューションの詳細がクライアントに(したがって、アプリケーション全体に)漏洩することです。これはセキュリティに影響を与える可能性があり、アプリケーションのバックエンドへの変更がより複雑になる可能性があることを意味します。 UUIDは、データベーステクノロジーから完全に独立した代替識別子を提供することで、この問題を解決する何らかの方法を提供します。

UUIDはこの問題の1つの解決策にすぎず、実際的な目的のために一意であることが保証されているという固有の利点があります。ただし、主キー以外のものを識別子として使用する努力をしている場合は、任意の文字列または別の数値識別子だけを使用すると、より適切なURLが得られることがあります。

もう1つの考慮事項は、エンティティのパブリックIDとしてGUID/UUIDを使用している場合、それらに何らかのインデックスが必要になる可能性があることです。整数よりもかなり多くのスペースを占めるため、インデックスははるかに大きくなります。

1
richzilla