web-dev-qa-db-ja.com

他のユーザーをキーフィールドとして使用できるのに、なぜID列を作成する必要があるのですか?

重複の可能性:
ルックアップテーブルの主キーとしてintを使用する理由

これまでのところ、すべてのテーブルにID列を作成することに慣れており、主キー理論についての意思決定を考えないようにするのに実用的です。

私の大学の教授は、各列について1つの一意の情報を構成する1つ以上のフィールドから主キーを作成するようクラスに提案しました。そして、はい、私は 代理キー の代わりに ナチュラルキー を適用する習慣を持ちたいです。ウィキペディアには、代理キーの長所と短所がリストされています。私は強くお勧めします この記事

私は人々がすべてに整数IDフィールドを使用し、誰もがこの方法を判断しないのを見てきました

  • 効率的に見える
  • 数値フィールドが使用されており、メモリ内の行あたりのサイズが原因で涼しく見えます

追加のIDフィールドは、実際には何の利点もない冗長なデータを作成するだけだと思い始めています。では、他の列をキーフィールドとして使用できるのに、なぜID列を作成する必要があるのでしょうか。

  • IDフィールドが32ビットの場合、4 ASCII文字がすでに存在することと同じです。
  • Idフィールドが64ビット整数の場合、それは8文字文字列なので、実際にはそれほどメモリを節約しません(ここで暗示されているのは、比較で使用されるメモリです。追加のid列は、使用されているメモリ(HDDとRAMの両方)に既に追加されています)。
  • 追加のIDフィールドを使用すると、インデックス作成コストが2倍になります。これは、主キーとして使用できる一意のフィールドにもインデックスを作成するためです。
  • たとえば、一意のユーザーIDを1つのブログ投稿に保存した場合など、キーフィールドとして使用できるデータが必要な場合は、追加の結合を作成します 、作成者の名前を表示するには、結合クエリを作成します。キーフィールドが作成者の名前である場合、関連するデータをブログ投稿テーブルに保存するため、結合する必要はありません。 意味のあるデータを含む外部キーフィールドにより、サブクエリまたは結合の必要性が減少します

enter image description here

  • 追加のIDフィールドを作成すると、メモリ負荷に「追加」されます。これは、一意の文字列フィールドの置き換えではありません。char-varcharフィールドを整数で置き換えず、を追加しますcolumnそしてそれはextra data flowを作成します。したがって、データストアの比較は、 "string"と "int + string"の間で行う必要があります。整数のidフィールドを追加してもスペースは節約されません。

一方

  • ユーザー入力から値を取得する主キーデータの割り当ては問題になる可能性がありますたとえば、人々は社会保障番号を間違って入力することがあり、実際に登録しようとする人は入力しません独自のポリシーにより、登録できない。これは、元の番号に数字を追加することで回避できます。

追加のリソース:

  1. Natural vcサロゲートキーの比較

記事を読んで私の結論は、自然キーについて考えることをスキップして毎回代理キーを使用する代わりに、可能な限り自然キーを使用する必要があるということです標準。

50

1-高速です。整数のJOINは、文字列フィールドまたは組み合わせのJOINよりもはるかに高速です。フィールドの。文字列より整数を比較する方が効率的です。

2-よりシンプルです。さまざまなデータ型の他のフィールドの組み合わせよりも、単一の数値フィールドに基づいてリレーションをマップする方がはるかに簡単です。

3-データに依存しません。IDで一致する場合、関係が変化することを心配する必要はありません。名前が一致する場合、名前が変わった(つまり、結婚した)場合はどうしますか?あなたが住所で一致した場合、誰かが引っ越したらどうなりますか?

4-より効率的です(自動インクリメント)intフィールドでクラスター化すると、断片化が減少し、データセットの全体的なサイズが減少します。これにより、関係をカバーするために必要なインデックスも簡素化されます。

[〜#〜]編集[〜#〜]

追加した特定のポイントに:

1および2-スペースの考慮はさておき、文字列よりもintを比較する方がはるかに高速です。また、可変長フィールドの長さ(通常、行ごとにフィールドあたり2バイト)を格納するために必要なオーバーヘッドを無視することもできます。

3-IDフィールドでクラスター化する場合、余分なものは追加されません。より効率的な行IDを使用しているため、スペースが節約されます。

4-そして、その人がユーザー名を変更すると、リンクはすべて壊れます。

5-ここで何について話しているのか本当にわかりません。データを保存する必要がありますが、それは正しいことですが、他のフィールドの組み合わせよりも、intでJOINをインデックス付けする方がはるかに効率的です。

41
JNK

そのようなフィールドを使用すると問題が発生することを経験から学んだためです。

私は20年間データベースアプリケーションを開発してきました。最も重要なことに、私はデータウェアハウスでの作業に5年間費やしました。当初、別のフィールドを選択することは問題ないようでした。次に、重複レコードが見つかりました。一意の検証が欠落している場合や、ユーザーが(頻繁に)マージする必要のあるさまざまな情報を提供していた場合など、レコードのマージと管理は悪夢でした。

識別子が(一意であると思われる場合でも)(または特に!)、真実ではない場合があります。例:米国の社会保障番号。それは人に固有でなければなりませんよね?もちろん、過去にユーザーが誤って入力したSSNでいくつかのレコードが入力された場合はどうなりますか?これで、新しいレコードに入力される新しい有効な番号との競合の問題が発生する可能性があります。副次的な注意点は、主キーはユーザーに関する想定につながるため、表示しないでください。また、WebサイトのURLの最適なセキュリティモデルには適していません。
常に考慮してください-ユーザーはこのURLをブックマークし、将来的に機能することを期待しますか?

だから人々は学んだ:

サロゲートに「ビジネス」の価値または意味がある場合は、「サロゲートキー」(SSNなど)を主キーとして使用しないでください。
代わりに、一意であり、アプリケーションデータに由来しない主キーを使用してください。

20
Michael Durrant

データを検索する場合、整数フィールドに基づいてこれを実行する必要があります。これが、多くの人がIDフィールドを使用する理由です。

しかし、多対多の関係に使用するテーブルがある場合、それは実際には必要ありません。次の2つのテーブルがあるとします。

テーブルニュース id整数タイトルvarcharアイテムテキスト

テーブルタグ id整数名varchar

ニュースのアイテムごとに1つ以上のタグを追加するため、テーブルを作成します。

テーブルnews_tags news_id整数tags_id整数

この場合、追加のid列を作成する必要はまったくありません。まったく必要ないからです。

12

特に定義する必要があるテーブル間にリレーションシップがある場合は、行を識別する最も簡単な方法であるため、ほとんどの人はデフォルトで主キーに自動インクリメントINTを使用します。

幸運なことに、すでに一意の識別子を持つ何かをモデル化できる場合は、それを主キーに使用することを検討します(例として、車のVINや携帯電話のIMEIなど)。

いわゆる複合キーもあります。基本的に、データベース内の2つ以上のフィールドが行を一意に識別します。私が一緒に仕事をしたほとんどの開発者(私も含む)は、通常これを使用しません。繰り返しますが、そうでない主な理由は、テーブル間の関係を管理することがより困難になるためです。

自然界では、物事は一意の識別子ではなく、他のエンティティとの関係によって定義されます。 idフィールドは、実際にはリレーショナルデータベースの単なるアーティファクトです。これは、オブジェクト関係マッピング(ORM)全体の問題の基礎です。

これはコースであり、内容を理解する必要があることを理解していますが、リレーショナルデータベースの外部でデータをモデル化する他の方法areがあることを忘れないでください。 NoSQLの動きはこれを証明しています。

4
hafichuk

他のフィールドを主キーとして使用できる場合は、それで十分です。ただし、[sql-server]でタグ付けしたので、情報を追加できます...

  • 主キーを持っていなかった、または必要としなかったテーブルを複製する必要がある場合は、主キーを作成する必要があります。このid列がある場合.. =パイのように簡単

  • ID列、特にIDENTITYcolumnsの列は、ほとんど更新されないという意味で(場合によっては)インデックスとしても適しています。テーブルから行を削除しないと、インデックスの断片化が減少します。

  • ID列は、必ずしもID列である必要はありません。あなたはdate_idを保存することができ(それがそうすることが理にかなっているいくつかのテーブルに対して)、それがユニークであるなら(例えば私が言ったように..あなたは1行= 1日であるテーブルを持っているなら)あなたはそれをキーまたはインデックスとして適用することができます

  • Create_date/entry_date列がなく、データを入力された順序で確認する必要がある場合。IDとしてID列があると、それが可能になります。

  • IDは外部キーとしても機能します。

1
Nonym

複合キーは機能しますが、単一の主キーの方が扱いやすい場合があります。たとえば、削除を実行すると、特定の行を選択するのが非常に簡単になります。

多くの場合、数値キーで検索する方が効率的です。

0
Paul Croarkin