3

自然主キーと代理主キーの戦いについて多くの記事を読みました。ユーザーがコンテンツを作成したテーブルのレコードを識別するために代理キーを使用することに同意します。

しかし、テーブルをサポートする場合、何を使用すればよいですか?

たとえば、架空のテーブル「orderStates」では。このテーブルの値は編集できません(ユーザーはこの値を挿入、変更、または削除できません)。

自然キーを使用する場合、次のデータがあります。

TABLE ORDERSTATES
{ID: "NEW", NAME: "New"}
{ID: "MANAGEMENT" NAME: "Management"}
{ID: "SHIPPED" NAME: "Shipped"}

代理キーを使用すると、次のデータが得られます。

TABLE ORDERSTATES
{ID: 1 CODE: "NEW", NAME: "New"}
{ID: 2 CODE: "MANAGEMENT" NAME: "Management"}
{ID: 3 CODE: "SHIPPED" NAME: "Shipped"}

次に例を見てみましょう。ユーザーが新しい注文を入力します。

自然キーを使用する場合、コードで次のように記述できます。

newOrder.StateOrderId = "NEW";

代わりに、追加の手順があるたびに代理キーを使用します。

stateOrderId_NEW = .... I retrieve the id corresponding to the recod code "NEW"

newOrder.StateOrderId = stateOrderId_NEW;

注文を新しいステータスに移動する必要があるたびに、同じことが起こります。

それで、この場合、一方のキータイプともう一方のキータイプを選択する理由は何ですか?

4

3 に答える 3

2

答えは:それは異なります。

コード内の順序状態を変更する例では、それらの状態の定数を作成する可能性がどの程度あるかを自問してください(たとえば、タイプミスを避けるため)。もしそうなら、両方が同じことを達成します。

新しい注文状態がフォームを介して送信される場合は、自然キーまたは代理キーのいずれかを使用して、可能な値のドロップダウン(たとえば)を作成します。違いはありません。

注文テーブルでクエリを実行していて、各注文の状態を出力したい場合には違いがあります。自然キーを使用すると、別の結合を行う必要がなくなり、(少しではありますが)役立ちます。

ストレージとクエリのパフォーマンスの観点から、ほとんどの場合、代理キーはそれぞれ小さく、高速です(テーブルサイズによって異なります)。

しかし、そうは言っても、それは慎重に検討する必要があります。個人的には、代理キーは教義のようなものになっていると思います。多くの開発者はそれらをすべてのテーブルで使用し、モデリングソフトウェアはテーブルの作成時にそれらを自動的に追加します。したがって、選択についてさまざまな反応が生じる可能性がありますが、それらの使用を禁止する厳格な規則はありません。賢く選ぶ:)

于 2012-10-05T16:12:17.953 に答える
1

一言で言えば:

  • 自然キーを使用すると、結合が少なくなる可能性があります1
  • ただし、より多くのスペースが必要になります2(したがって、キャッシュのパフォーマンスが低下します3)。

ここには厳格なルールはありません。まず、そのようなJOINが必要かどうかを判断し、必要な場合は、それを排除することで、ストレージを増やして代償を払う価値があるかどうかを判断します。そのための唯一の方法は、現実的な量のデータを測定することです。

ところで、自然対代理の議論には、次のような他の考慮事項があります...

  • カスケード更新、
  • クラスタリング、
  • ひし形の依存関係など。

...しかし、ほとんどの場合、それらはあなたのケースには当てはまりません。


1自然キーはFKを介して「メイン」テーブルに移行されるため、メインテーブルの行と一緒にする必要がある場合は、JOINを完全に回避できます。ところで、(非キーを取得するために)別のJOINが必要な場合、この方法でそれを排除することはできません。

2おそらく、「メイン」テーブルは大きいので、多くの文字列(移行された自然キーの場合)を格納する方が、多くのint(移行されたサロゲートの場合)を格納するよりもスペース効率が低くなります。メインテーブルが小さい場合は、どちらの方法でもほとんど問題になりません。

3行は「太い」ので、1つのデータベースページに収まる行は少なくなります。キャッシュは通常、ページレベルで実装されます。

于 2012-10-06T12:02:40.013 に答える
0

私が正しく理解していれば、最初の例では、テーブルの主キーが文字列(varchar)であるのに対し、2番目の例では主キーが整数であることが示されています。主キーは、おそらく別のテーブルの外部キーになります。

明らかに、整数を格納すると、varcharを格納するよりも少ないディスク領域が使用されます。特に、最長のvarchar(この場合は「管理」)にスペースを割り当てる必要があるためです。整数によるインデックス作成は、文字列によるインデックス作成よりも高速だと思います(インデックスの占有スペースも少なくなります)。

最初の例では、主キーと「名前」フィールドが同じ値になっています。名前を変更しても主キーは変更されませんが(したがって、外部キーとして「OrderStates」を使用するテーブルには影響しません)、論理的な切断が発生します。主キーとして「NAME」を使用できますが、値は「Person」になります。 '。

次のようなクエリを作成するのが通例です。

select orders.ordname
from orders
inner join orderstatus on orders.status = orderstatus.id
where orderstatus.name = 'NEW'

正直なところ、ステータスの名前を確認するのではなく、フラグフィールドを使用して、ステータスが初期の「新規」ステータスを示しているかどうかを示します。名前を変更しても、ステータスは初期ステータスのままです。

ジェネレーターを使用して、一意であることが保証されているキーを提供できますが、「自然」キーを使用する場合は、衝突をチェックする必要があります。

于 2012-10-05T15:35:52.487 に答える