考慮すべき1つのことは、主キーとクラスター化インデックスは同じものではないということです。主キーは制約であり、データが存続するルール(つまり、データの整合性)を扱います。効率/パフォーマンスとは関係ありません。主キーでは、キー列が(組み合わせて)一意であり、(個別に)NOT NULLである必要があります。PKは一意のインデックスを介して適用されますが、クラスター化または非クラスター化することができます。
クラスタ化インデックスは、テーブル内のデータを物理的に(つまり、ディスク上で)並べ替え、パフォーマンスを処理する手段です。データの整合性とは関係ありません。クラスタ化インデックスは、キー列は(組み合わせて)一意である必要がありますが、そうである必要はありません。ただし、クラスタ化インデックスはデータの物理的な順序であるため、何であれ各行を一意に識別する必要があります。したがって、一意性を要求するように設定しない場合、非表示の4バイトの「一意化」列を介して独自の一意性が作成されます。その列は非一意のクラスター化インデックスに常に存在しますが、キーフィールドが(組み合わせて)一意である場合は、領域を占有しません。この「一意化」列がどのように機能するか(クラスター化インデックスと非クラスター化インデックスへの影響の両方)を直接確認するには、PasteBinに投稿したこのテストスクリプトを確認してください:UniquifierサイズをテストするT-SQLスクリプト。
したがって、主な質問:
自動インクリメントid
フィールドをcompany_id
追加し、それを主キーとして使用する方が効率的ですか、それとも不要なオーバーヘッドが追加されますか
はこれら2つの概念を融合しているため、明確に重複している部分もありますが、個別に対処する必要があります。
必要がありますIDENTITY
列が追加されるか、不要なオーバーヘッドでしょうか?
INT IDENTITY
列を追加し、それを使用してPKを作成すると、クラスター化されたPKであると想定して、すべての行に4バイトが追加されます。この列は表示され、クエリで使用できます。これは外部キーとして他のテーブルに追加できますが、この特定のケースでは発生しません。
INT IDENTITY
列を追加しないと、このテーブルにPKを作成できません。ただし、このUNIQUE
オプションを使用しない限り、テーブルにクラスター化インデックスを作成できます。この場合、SQL Serverは「uniquifier」と呼ばれる非表示の列を追加します。これは、上記のように動作します。列は非表示であるため、クエリで使用したり、外部キーの参照として使用したりすることはできません。
したがって、効率に関する限り、これらのオプションはほぼ同じです。はい、一部の行(最初の一意のキー値を持つ行)が0バイトを占めるため、非一意のクラスター化インデックスが占めるスペースはわずかに少なくなりますが、IDENTITY
/ PKのすべての行は4バイトを占めます。ただし、0バイトの行(特に、予想される少量の行)では、違いに気付くのに十分ではなくID
、クエリで列を使用できるという利便性を上回ります。
INT IDENTITY列またはorg_path
永続的な計算列のハッシュ?
org_path
値に基づいて行を検索しないことを考えると、永続的な計算列のオーバーヘッドに加えて、計算列と照合するためにクエリでそのハッシュを計算する必要があることは意味がありません(これは私の最初の文言/質問の詳細に基づいた、ここの改訂履歴で利用できる元の提案)。この特定のケースでは、INT IDENTITY
「ID」列がおそらく最適です。
キー列の順序
ことを考えるとID
列はほとんど、これまでの場合は、クエリで使用しない、されると、二つの主なユースケースは、「すべての行」または「特定のためのすべての行のいずれかを取得するためにあることを考えるcompany_id
」、私は上のPKを作成しますcompany_id, id
。そして、これは行が順番に挿入されないことを意味するので、私はFILLFACTOR
90 を指定します。フラグメント化を減らすために、定期的なインデックスメンテナンスを確実に行う必要もあります。
二番目の質問
company_idが別のテーブルの主キーであるという事実は、ここで効果がありますか
番号。
引き金
以来org_path
内の値がcompany_id
一意である、あなたはまだ上のトリガーを作成する必要がありINSERT, UPDATE
、これを施行します。トリガーでは、やるIF EXISTS
だろうし、クエリでCOUNT(*)
とGROUP BY company_id, org_path
。何かが見つかった場合は、a ROLLBACK
を発行してDML操作をキャンセルしてから、RAISERROR
重複があることを伝えます。
照合
私の最初の回答では(質問の元の文言/まばらな詳細に基づいており、ここの改訂履歴にあります)、バイナリ(つまり_BIN2
)照合を使用することを提案していました。正確に何であるかについての洞察org_path
を得たので、バイナリ照合を使用することはお勧めしません。分音記号が存在しますので、あなたはない言語的等価性を利用することにしたいです。