はい、主キーに数値型の代わりに文字列を使用することにはマイナスの影響があり、そのPKがクラスター化されている場合(実際にそうです)の場合はさらにマイナスになります。ただし、文字列フィールドを使用した場合の効果の程度は、a)このテーブルに含まれる行の数、およびb)このPKに対して外部キーを持つ他のテーブルの行の数の関数です。このテーブルに1万行しかなく、他のいくつかのテーブルにも10万行しかない場合、そのフィールドを介してこのテーブルにFKすると、それほど目立たなくなる可能性があります。ただし、行数が増えると、これらの影響は確実に顕著になります。
クラスタ化インデックスのフィールドが非クラスタ化インデックスに引き継がれることを考慮する必要があります。つまり、1行あたり最大40バイトを調べるだけでなく、(40 * some_number)バイトを調べることになります。また、FKテーブルでは、行に同じ40バイトがあり、JOINで使用されているため、そのフィールドに非クラスター化インデックスが存在することが多いため、FKを実行するすべてのテーブルで実際に2倍になります。これです。40バイト* 100万行*それの10コピーは心配する必要がないと考える傾向がある場合は、私の記事「ディスクは安いです!」を参照してください。ORLY?これは、この決定によって影響を受けるすべての(または少なくともほとんどの)領域を詳しく説明しています。
考慮すべきもう1つの点は、特にバイナリ照合を使用しない場合(通常、大文字と小文字を区別しないデータベースのデフォルトを使用していると想定)、文字列のフィルタリングとソートは、INT
/ を使用する場合よりもはるかに効率が悪い(つまり時間がかかる)ことBIGINT
です。これは、このフィールドでフィルタリング/結合/ソートするすべてのクエリに影響します。
したがって、CHAR(5)
クラスター化されたPKのようなものを使用することはおそらく問題ありませんが、それもCOLLATE Latin1_General_100_BIN2
(またはそのようなもので)定義されている場合がほとんどです。
そして、[CODE]
これまでの価値は変わることができますか?はいの場合は、それをPKとして使用しない理由です(FKをに設定した場合でもON UPDATE CASCADE
)。変更できない場合、または変更できない場合は問題ありませんが、クラスター化されたPKとして使用しない理由はまだ十分にあります。
もちろん、現在PKにこのフィールドがすでにあるように見えるため、質問のフレーズが誤っている可能性があります。
いずれにしても、最善のオプションは[ID_CODE]
、クラスタ化PKとして使用し、関連テーブルのそのフィールドをFKとして使用し、[CODE]
として保持UNIQUE INDEX
することです(つまり、「代替キー」です)。
更新
この回答に関するコメントで、この質問に基づくもう少し詳しい情報:
[ID_CODE]は、PRIMARY KEYとして、[CODE]列を使用してテーブルを検索する場合の最良のオプションですか?
これはすべて、非常に多くの要因に依存します。そのいくつかは、すでに述べましたが、以下に述べます。
主キーは、外部キーによって参照されているかどうかに関係なく、個々の行を識別する方法です。システムが行を内部的に識別する方法は、ユーザーが自分やその行を識別する方法に関連していますが、必ずしも同じであるとは限りません。一意のデータを持つNOT NULL列は機能しますが、特にPKが実際にFKによって参照されている場合は、考慮すべき実用上の問題があります。たとえば、GUIDは一意であり、さまざまな理由で実際に使用するのを好む人もいますが、それらはクラスター化インデックスには非常にNEWSEQUENTIALID
適していません(優れていますが、完全ではありません)。一方、GUIDは代替キーとしては問題なく、アプリが行を検索するために使用しますが、JOINはINT(または同様の)PKを使用して行われます。
これまでのところ、[CODE]
フィールドがすべての角度からシステムにどのように適合するかを教えていません。これは、これが行のルックアップ方法であると述べたこと以外に、すべてのクエリまたは一部のクエリについてですか?したがって:
[CODE]
値について:
- どのように生成されますか?
- インクリメンタルですか、それとも擬似ランダムですか?
- 均一の長さですか、それとも可変長ですか?
- 使用されている文字は?
- アルファベット文字を使用する場合:大文字と小文字が区別されますか、それとも区別されますか?
- 挿入後に変更することはできますか?
この表について:
- 他のテーブルはこのテーブルに対してFKを行いますか?または、明示的に外部キー化されていなくても、これらのフィールド(
[CODE]
または[ID_CODE]
)が他のテーブルで使用されていますか?
-
[CODE]
個別の行を取得するために使用される唯一のフィールドである場合、[ID_CODE]
フィールドはどのような目的に役立ちますか?それが使用されない場合、なぜそれが最初にあるの[CODE]
ですか(「これは、フィールドが変更される可能性がありますか?」に対する回答に依存する可能性があります)?
- このテーブルの行数は?
- 他のテーブルがこのテーブルを参照する場合、それらのそれぞれにいくつの行が含まれていますか?
- このテーブルのインデックスは何ですか?
この決定は、「NVARCHARはいまたはいいえ」の質問だけで行うことはできません。もう一度言いますが、一般的に言ってそれは良い考えではないと思いますが、確かにそれが良い時もあります。このテーブルのフィールドが非常に少ないことを考えると、これ以上、または少なくとも多くないインデックスがある可能性は低いです。したがって[CODE]
、クラスタードインデックスとしてどちらの方法を使用してもかまいません。そして、他のテーブルがこのテーブルを参照していない場合は、それをPKにすることもできます。しかし、他のテーブルがこのテーブルを参照し[ID_CODE]
ている場合は、クラスター化されていない場合でも、フィールドをPKとして選択します。