10

私の友人と私はウェブサイトを構築していて、大きな意見の相違があります。このサイトの中核は、「人」に関するコメントのデータベースです。基本的にはコメントを入力でき、コメントの対象者を入力できます。次に、視聴者は、コメントまたは人物名の一部に含まれる単語をデータベースで検索できます。完全にユーザー生成です。たとえば、ある人の名前のつづりを間違えたバージョンについてコメントを投稿したい人がいる場合、それは可能であり、それは問題ありません。そのため、複数の異なるエントリ (ミドル ネーム、ニックネーム、スペルミスなど) としてリストされている異なる人物のスペルが複数ある場合がありますが、これはすべて問題ありません。人々がランダムな人や架空の人についてコメントするかどうかは気にしません.

とにかく、問題はデータベースをどのように構築しているかです。現時点では、コメント ID を主キーとする 1 つのテーブルだけで、コメントの対象となる「人物」のフィールドがあります。

コメントID - コメント - 人物

1 - 「彼は変だ」 - ジョン・スミス

2 - 「臭い女の子」 - ジェニー

3 - 「ゲイ」 - ジョン・スミス

4 - 「20ドル貸して」 - Jennyyyyyyyyy

すべてが正常に機能しています。データベースを使用して、特定の「人物」に対するすべての「コメント」を一覧表示するページを作成できます。しかし、彼はデータベースが正規化されていないことに執着しています。私はノーマライゼーションについて読み、彼が間違っていることを知りました。コメント ID は一意であり、「コメント」と「人」を指示するため、テーブルは現在正規化されています。今、彼は「物」であるため、「人」は自分のテーブルを持つべきだと主張しています。「人」は実際にはより大きなコンテナですが(1人の「人」はそれらについて多くの「コメント」を持つことができます)、データベースは「人」が属性であると問題なく動作するようですコメントID。さまざまな SQL 選択に対してさまざまな PHP 呼び出しを使用して、魔法のように出力がより洗練されたように見えるようにし、ユーザーが検索して結果を表示できるようにしますが、実際には、セットアップは非常に簡単です。私は現在、ユーザーに親指と親指でコメントをランク付けさせており、同じテーブルの別のフィールドとして「スコア」を保持しています。

「人」には独自の「スコア」や独自の属性がないため、現在、一意の「人」エントリ用に別のテーブルを用意する必要はないと思います。コメントのみが行います。私の友人はとてもしつこいので、効率のために必要です。最後に私は、「別のテーブルを作成して、'person' を独自のフィールドにする場合、2 番目のフィールドは何にしますか? テーブルに 1 つの列しかない場合、それは無意味に思えるので、同意します。後で 'person' に独自のテーブルを与える必要が生じるかもしれませんが、それなら対処できます。」彼は次に、文字列を主キーにすることはできず、現在のテーブルの「人」を数値に変換すると、その数値が新しい「人」テーブルの主キーになると述べました。私にはこれは不必要に思え、現在のテーブルが読みにくくなります。彼はまた、2 番目のテーブルを後で作成することは不可能であり、後で必要になる可能性があることを予測する必要があると考えています。

誰が正しいですか?

4

11 に答える 11

9

私の意見では、あなたの友人は正しいです。

人は別のテーブルに住む必要があり、正規化を試みる必要があります。ただし、無理をしないでください。

長い目で見れば、サイトでもっと多くのことをしたいと思うかもしれません。たとえば、複数のファイル (写真など) を 1 人に添付したい場合は、正規化に非常に感謝するでしょう。

于 2010-09-10T15:18:57.050 に答える
8

person の新しいテーブルを作成し、 person 属性の代わりにそのテーブルのキーを使用することは、正規化とは何の関係もありません。他の理由で良い考えかもしれませんが、そうしても、そうしないよりもデータベースが「より正規化」されません。その通りです。正規化に関する限り、別のテーブルを作成する必要はありません。

于 2010-09-10T17:27:38.030 に答える
3

私はあなたの友人に投票します。私は標準化して将来の計画を立てるのが好きです。たとえそれが必要ない場合でも、この標準化はとても簡単で、文字通り時間がかかりません。SQL をクリーンにし、自分でテーブルを結合する必要をなくすために、クエリを実行するビューを作成できます。

于 2010-09-10T15:19:31.683 に答える
2

すでにすべての能力に達しており、能力を拡張する計画がない場合は、そのままにしておくと思います。

さらに追加する予定がある場合、つまり、人々がアカウントを持てるようにするなど、実際には何かを計画している場合は、データを Person テーブルと Comments テーブルに分けるのが賢明かもしれません。難しいことではなく、機能を簡単に拡張できます。

于 2010-09-10T15:19:45.747 に答える
2

あなたが正しい。

Person一般的にはそうかもしれませんが、あなたのモデルではそうではありません。人々が話している人物を適切に特定するように人々を煩わせようとするなら、Person表が必要になります。たとえば、コメントがデータベースに既に登録されている個人に関するものである場合。

しかし、ここでは、ID のない非構造化データがあるように見えます。そして、「jenny」と「jennyyy」が実際に同一人物であるかどうかを確認することには誰も興味がありません。「jenny doe」と「私のいとこ」は言うまでもありません...

于 2010-09-10T15:29:52.930 に答える
1

さて、2つの考え方があります。1 つは、可能な限り最も正規化された方法でデータ モデルを作成し、さらに効率が必要な場合は非正規化することです。もう1つは、基本的に「仕事に必要な最小限の作業を行い、要件の変化に応じて変更する」ことです。YAGNI としても知られています (必要ありません)。

それはすべて、これがどこに行くかによって異なります。これがすべてである場合、あなたのアプローチはおそらく問題ありません。時間の経過とともに新しい機能でそれを改善するつもりなら、あなたの友人は正しい.

于 2010-09-10T15:24:42.367 に答える
1

正規化はすべて、機能依存関係 (FD) に関するものです。完全に正規化する前に、データ モデルの属性に存在するすべての FDを特定する必要があります。

あなたが持っているものを確認しましょう:

  • (FD: -> )の任意のインスタンスがCommentId機能的に決定されます。PersonCommentIdPerson
  • (FD: -> )の任意のインスタンスがCommentId機能的に決定されます。CommentCommentIdComment
  • (FD: -> )の任意のインスタンスがCommentId機能的に決定されます。UserIdCommentIdUserId
  • (FD: -> )の任意のインスタンスがCommentId機能的に決定されます。ScoreCommentIdScore

CommentIdここにあるものはすべてand CommentId単独の依存属性です。これにより、上記の属性のすべてまたはサブセットを含むリレーション (テーブル) を正規化する必要があると思われるかもしれません。

最初に自問することは、CommentIdとにかく属性を作成した理由です。厳密に言えば、これは製造された属性であり、「実際の」ものとは何の関係もありません。CommentId は、一般に代理キーと呼ばれます。代理キーは、他の属性グループに対応する一意の値セットを表す、単なる構成値です。では、どの属性のグループがCommentId サロゲートになるのでしょうか? 次の質問をして、モデルに新しい FD を追加することで、それを理解できます。

  • 1) コメントは一意である必要がありますか? その場合、FD: Comment->CommentIdは true でなければなりません。
  • 2) 別の人物に関するものである限り、同じコメントを複数回行うことはできますか? そうであれば、FD: Person+ Comment->CommentIdは true でなければならず、上記 1 の FD は false です。
  • 3) 異なる UserId によって作成された場合、同じ人について同じコメントを複数回作成できますか? そうであれば、1 と 2 の FD は真ではありませんが、FD: Person+ Comment+ UserId->CommentIdは真である可能性があります。
  • 4) 同じ UserId で同じ人について同じコメントを複数回作成できますが、スコアは異なりますか? これは、FD: Person+ Comment+ UserId' + Score->CommentIdが true で、その他が false であることを意味します。

上記の 4 つの FD のうちの 1 つだけが真である必要があります。どちらであっても、データ モデルの正規化方法に影響します。

FD: Person+ Comment+ UserId->CommentIdが真であることが判明したとします。論理的な結果は次のとおりです。

  • Person+ Comment+UserIdCommentId同等のキーとして機能しますScore
  • Score両方のキーではなく一方のキーとの関係に配置する必要があります (推移的な依存関係を避けるため)。CommentIdサロゲートとして特別に作成されたので、当然の選択です。
  • キーをそのサロゲートに結び付けるにはCommentIdPersonComment、 で構成される関係が必要です。UserId

理論的な観点からはCommentId、データ モデルまたはデータベースを機能させるために代理キーは必要ありません。ただし、その存在は関係の構築方法に影響を与える可能性があります。

代理キーの作成は、ある程度重要な実用上の問題です。Person代理キーを使用せず、その代わりに完全な属性セット+ Comment+を使用することを選択したUserId場合、特に複数のテーブルで外部キーまたは主キーとして必要な場合にどうなるかを検討してください。

  • コメントは複数のテーブルで繰り返されるため、データベースに大量のスペース オーバーヘッドを追加する可能性があります。おそらく数文字以上の長さです。
  • 誰かがコメントを編集することを選択した場合はどうなりますか? その変更は、コメントがキーの一部であるすべてのテーブルに反映される必要があります。きれいな光景ではありません!
  • 長くて複雑なキーのインデックスを作成すると、多くのスペースが必要になったり、更新のパフォーマンスが低下したりする可能性があります

代理キーが決定する属性に関連付けられた値に何をしても、代理キーに割り当てられた値は変わりません。従属属性の更新は、代理キーを定義する 1 つのテーブルに限定されるようになりました。これは実用上非常に重要です。

のサロゲートを作成する必要があるかどうかに戻りますPersonPerson多くの、またはいくつかの FD の左側に住んでいますか? 存在する場合、その値はデータベースを通じて伝播され、そのサロゲートを作成する場合があります。Person がテキスト属性であるか数値属性であるかは、代理キーの作成の選択には関係ありません。

あなたが言ったことに基づいて、せいぜい代理を作成するための弱い議論がありますPerson. この議論は、その値が将来のある時点でキーまたはキーの一部になる可能性があるという疑いに基づいています。

于 2010-09-10T20:38:08.173 に答える
1

person 列をユーザーなどに関連付けるつもりがまったくなく、データの一貫性やデータの整合性チェックが必要ないように見える場合、これがリレーショナル データベースにあるのはなぜでしょうか? これは nosql データベースのユースケースではないでしょうか? または、何か不足していますか?

于 2010-09-10T20:45:52.410 に答える
0

これが取引です。何かを作成するときはいつでも、それが成長する余地があることを確認したいと思います。あなたはあなたのプログラムの将来のプロジェクトと将来の進歩を予測しようとしています。このシナリオでは、現在、1つのフィールドのみを保持するpersonsテーブルを追加する必要はないと言っています(int IDフィールドとperson名がある場合、IDはカウントされません)。ただし、将来的には、名前、名前、電子メールアドレス、追加日など、そのような人に他の属性を設定したい場合があります。

過度の正規化は確かに有害ですが、私は個人的に別のより大きなテーブルを作成して、将来新しい機能を簡単に追加できるように、追加のフィールドを持つ人を保持します。

于 2010-09-10T15:20:12.507 に答える
0

このデータベースを使えば大丈夫だと思うかもしれませんが、データベースからユーザーにもっと知ってもらいたい場合、将来的に問題が発生する可能性があります。 「abc」。この場合、コメントのテーブル全体を調べてカウントし続ける必要があります。この代わりに、すべての人に「カウント」という属性を設定し、コメントが作成されるたびに値を増やすことができます。人。
正規化に関する限り、冗長性を減らし、データベースを直感的に理解できるようにするため、正規化されたデータベースを使用することをお勧めします。データベースが将来的に大きくなると予想される場合は、正規化が存在する必要があります。

于 2014-03-17T13:58:52.903 に答える
0

ユーザーとやり取りするときはいつでも、専用のテーブルが必要です。次に、テーブルを結合して、そのユーザーの ID を参照するだけです。

user -> id | username | password | email

comment -> id | user_id | content

コメントをユーザーに結合する SQL:

SELECT user.username, comment.content FROM user JOIN comment WHERE user.id = comment.user_id;

将来、その特定のユーザーに関する情報を見つけたい場合に、非常に簡単になります。余分な労力は無視できます。

各コメントの「スコア」についても、別の表にする必要があります。そうすれば、ユーザーを「好き」または「嫌い」に結び付けることができます。

于 2013-12-17T20:07:49.207 に答える