web-dev-qa-db-ja.com

ID /主キーのIntと公開識別子のGuid、ベストプラクティス?

ほとんどの場合、テーブルのID /プライマリ(自動インクリメント)クラスター化キーにはintを使用します。クエリやデバッグ、SSMSでのバウンスなど、さまざまな理由で簡単に実行できます。

典型的なCRUDインターフェイス(作成、読み取り、更新、削除)を備えたアプリケーションを作成していて、intではなくurlでGuidを使用したい場合があります。

テーブルの例は次のようになります。

_CustomerId int identity(1,1) PK clustered
CustomerName nvarchar(100)
Guid uniqueidentifier
_

過去に誰かが詳細レコードを表示していたとき、私はアイデンティティを渡すだけでした:

_/app/details/1 <-- id of the record
_

多くのアプリケーションで見たように、私はこれのアイデアが好きです:

_/app/details/guidinstead
_

要するに、アイデンティティとしてのintと、公開キーとしてのGUIDです。

私が心配しているのは、この方法を使用した特定のテーブルが大幅に成長した場合のパフォーマンスです。これにはビジネス上の理由があります。アクセス権を持つユーザーは、特定のリンクを他のユーザーと共有して詳細を表示できるからです。

別の理由は、特定のレコードを表示する「権利」があるかどうかを判断する場合と同様に、クエリのオーバーヘッドを別の方法で削減するためです。

最初のヒットは、レコードの実際のIDを検索することです。その後、レコードのすべてのネストされたリソースは、多くのテーブルにわたるIDフィールドの結合で簡単に実現されます。

現在、[Guid]のuniqueidentifier列にインデックスが設定されていません。

まとめると、URLに増分キーが表示されないようにしたいと思います。テーブルに大量のデータが含まれる場合に、後で悪夢を見たくないです。挿入と更新は現在、int/identity列を使用しています。

操作は次のとおりです。

  1. レコードを作成するときは、_.NET_のGuid.NewGuid()を使用してGuid列を生成します。
  2. レコードを更新するとき、CustomerIdに基づいてGuidを見つけ、それに応じて更新します。これは通常、他のリレーショナルテーブルでも更新/挿入され、CustomerIdが必要になるためです。そうするために。
  3. レコードの詳細を表示する場合、それは_WHERE Guid = @Guid_です。
  4. レコードを削除する場合、それは_WHERE Guid = @Guid_です。

質問:

  1. テーブルにintとguidの両方を含める価値はありますか、それともintを完全に削除する必要がありますか?
  2. テーブルに配置する必要がある他の設定はありますか?
  3. より良いオプションはありますか?それほど多くのスペースを取らないある種のシーケンスを推測することはもう不可能ですか?

初期段階なので、今すぐ変更するのは簡単です。

1
user1447679

テーブルにintとguidの両方を含める価値はありますか、それともintを完全に削除する必要がありますか?

はい、ID列を一意のクラスター化インデックスにして、挿入をテーブルにのみ追加できることを利用できるという観点から、非クラスター化主キーをGUIDレコードを検索する際のセキュリティと一意性の両方の列。

テーブルに配置する必要がある他の設定はありますか?

[〜#〜] newsequentialid [〜#〜] を使用してGUID挿入のランダム性を低くするか、動作を一致させることを検討してください ネイティブで.NET 。誰かが非常に熱心である場合、おそらく次の順次GUIDを推測する可能性があります。そのような注意を引くと思われる場合は、通常のランダムな方法で生成してください。

また、ID列をBIGINTにします。それらは、INTよりも使い果たすのがはるかに困難です。行ごとに4バイト余分に取り掛かった人は、INTが不足した後にその属性を変更するプロセスに対処したことはありません。

より良いオプションはありますか?それほど多くのスペースを取らないある種のシーケンスを推測することはもう不可能ですか?

いいえ、あなたは正しい軌道に乗っています。

2
Erik Darling

私が経験したように、ID型の列のクラスター化インデックスは、クラスター化インデックスが並べ替えられた順序でデータを格納するため、シーケンシャル/最後のページ書き込みにより、多くのページラッチを引き起こします。

動作は、行のサイズと数、またはテーブルのトランザクションによって異なります。私が働いていた組織の1つでは、以前はほぼ35〜40 GB /日、1億〜2億のトランザクションを受け取っていました。テーブルのID列のクラスター化インデックスは、クラスター化インデックスを候補キーに移動する必要があったため、ラッチの競合を引き起こしていました。

したがって、テーブルがOLTP目的の場合は、非クラスター化インデックスを使用してプライマリを作成し、クラスター化インデックスのGUID列を使用することをお勧めします。

GUID列を検索条件として使用したいので、(キールックアップを回避することにより)SELECTクエリのパフォーマンスが向上するだけでなく、同時にページラッチを減らすのに役立ちます) OLTP table)です。

今質問に来ています。

テーブルにintとguideの両方を含める価値はありますか、それともintを完全に削除する必要がありますか?

どちらの列もテーブル内のレコードを一意に識別しますが、両方の列を保持することの欠点はありません。 IDは、不足しているレコードやその他のものを特定するのに役立ちます。

テーブルに配置する必要がある他の設定はありますか?

エリックの提案とは別に、

  1. 適切なインデックスfillfacterを使用します。
  2. DBデータファイルに追加の割り当てスペースがあることを確認してください(実行時のスペース割り当てを防止します)。
  3. DBトランザクションログのサイズを設定することを忘れないでください。記事 transaction-log-vlfs-too-many-or-too-few が役立ちます。

より良いオプションはありますか?それほど多くのスペースを取らないある種のシーケンスを推測することはもう不可能ですか?

スペースを取りませんが、GUIDとはかなり異なります。 SP(テーブルにレコードを挿入して、テーブルのすべてのレコードに対してハッシュ値を生成するために使用できます。きっとあなたは [〜 #〜]ハッシュバイト[〜#〜]

ありがとう!

0
Rajesh Ranjan

これにはビジネス上の理由があります。アクセス権を持つユーザーは、特定のリンクを他のユーザーと共有して詳細を表示できるからです。

別の理由は、特定のレコードを表示する「権利」があるかどうかを判断する場合と同様に、クエリのオーバーヘッドを別の方法で削減するためです。

すでにauthorizing userをお持ちの場合は、なぜQuery Stringを心配する必要がありますか?主な関心事はセキュリティです。すでに各URLでユーザーを検証している場合は、クエリ文字列について心配する必要があります。

この点をクリアできますか?

ほとんどの場合、Query Stringなしで実行できます。多くの人々はそれをUserSEOに友好的にするために友好的なURLを使います。

私が意味したことは、承認を処理していない場合、GUIDはINTよりも少し安全ですが、内部で承認と [〜#〜] idor [〜#〜] を使用しています。

0
KumarHarsh