4

現在、2 つの異なるデータベース設計のどちらかを選択しています。単純なものよりもデータを分離する複雑なもの。より複雑な設計にはより複雑なクエリが必要になりますが、単純なものにはいくつかのフィールドがあります。null

以下の例を検討してください。

複雑:

複雑

より簡単:

よりシンプルに

上記の例は、通常のユーザーと Facebook ユーザーを分離するためのものです (最終的には同じデータにアクセスしますが、ログイン方法が異なります)。最初の例では、データが明確に分離されています。2 番目の例はかなり単純ですが、行ごとに少なくとも 1 つのnullフィールドがあります。facebookUserId通常のユーザーの場合はnull にusernameなりpasswordますが、Facebook ユーザーの場合は null になります。

私の質問は次のとおりです。何が好まれますか?長所短所?長期間にわたって維持するのが最も簡単なのはどれですか?

4

5 に答える 5

3

まず、カークが言ったこと。これは、それぞれの代替設計がもたらす可能性のある結果をうまくまとめたものです。第二に、他の人が同じ問題で何をしたかを知ることは価値があります。

あなたが概説するケースは、ERモデリングサークルでは「ER専門化」として知られています。ER の特殊化は、サブクラスの概念の別の表現です。提示する図は、SQL テーブルにサブクラスを実装する 2 つの異なる方法です。1 つ目は、"Class Table Inheritance" という名前です。2 つ目は、"Single Table Inheritance" という名前です。

クラステーブルの継承を使用する場合は、「共有主キー」という名前のさらに別の手法を適用する必要があります。この手法では、facebookusers と normalusers の id フィールドは、users の id フィールドのコピーになります。これにはいくつかの利点があります。これにより、関係の 1 対 1 の性質が強化されます。サブクラス テーブルに追加の外部キーを保存します。結合を高速化するために必要なインデックスが自動的に提供されます。また、特殊化されたデータと一般化されたデータを結合するための単純で簡単な結合が可能になります。

SO のタグとして、「ER 特殊化」、「単一テーブル継承」、「クラス テーブル継承」、および「共有主キー」を検索できます。または、Web 上で同じトピックを検索することもできます。最初に学ぶことは、Kirk が非常にうまく要約したことです。さらに、それぞれのテクニックの使い方を学びます。

于 2012-11-01T09:41:59.533 に答える
2

素晴らしい質問です。

これは、コードであろうとデータベースであろうと、実装することを選択する可能性のある抽象化に適用されます。Facebook ユーザーと「通常の」ユーザー用に別のクラスを作成しますか、それとも 1 つのクラスで 2 つのケースを処理しますか?

最初のオプションはより複雑です。なぜ複雑なのですか?拡張性が高いからです。追加の認証方法 (Twitter ID のテーブルなど) を簡単に含めたり、Facebook テーブルを拡張してその他の Facebook 固有の情報を含めることができます。各認証方法に固有の情報を独自のテーブルに抽出し、それぞれを独立できるようにしました。これは素晴らしい!

トレードオフは、クエリと選択と挿入により多くの労力がかかり、より厄介になる可能性が高いことです。ダースの異なる認証方法に対してダースのテーブルは必要ありません。また、メリットが得られない限り、2 つの認証方法に対して 2 つのテーブルが必要になることはありません。この柔軟性が必要ですか?認証方法はすべて似ています。ユーザー名とパスワードがあります。この抽象化により、より多くのメソッド固有の情報を保存できますが、その情報は存在しますか?

2 番目のオプションは、最初のオプションの逆です。簡単ですが、将来の認証方法をどのように処理しますか? また、認証方法固有の情報を追加する必要がある場合はどうすればよいでしょうか?

個人的には、この認証コンポーネントがシステムにとってどれほど重要かを評価してみたいと思います。YAGNI を覚えておいてください -あなたはそれを必要としません - そして過度に設計しないでください. 最初のオプションが提供する拡張性が必要でない限り、2 番目のオプションを使用してください。必要に応じて、いつでも後で抽出できます。

于 2012-10-31T23:46:55.837 に答える
2

これは、使用しているデータベースによって異なります。たとえば、Postgres には、あなたの例に最適なテーブル継承があります。こちらをご覧ください: http://www.postgresql.org/docs/9.1/static/tutorial-inheritance.html

テーブルの継承がない場合でも、ビューを作成してクエリを簡素化できるため、ここでは「複雑な」例を選択することをお勧めします。ここで、最初の例よりも時間が無限にある場合 (この単純な例では、テーブルの継承が好まれます)。

ただし、これは物事をより複雑にするため、実装と保守により多くの時間がかかります。このようなテーブル階層が多数ある場合は、パフォーマンスに影響を与える可能性もあります (多くのテーブルを結合する必要があるため)。私はかつて、そのような階層を (概念的に) 過度に使用するデータベース スキーマを開発しました。最終的に、階層を概念的に維持することにしましたが、実装の階層が非常に複雑になり、保守できなくなったため、階層をフラットにすることにしました。

階層を平坦化する場合null、値を使用しないことを検討することもできます。これは、物事をより困難にすることが証明される可能性があるためです (代わりに、-1または何かを使用することもできます)。

これらの考えがお役に立てば幸いです。

于 2012-10-31T22:34:01.730 に答える
1

あえて3番目を提案させてください。拡張性に対応する 1 つ (または 2 つ) のテーブルを導入できます。私は個人的に、不均一に適用可能な列を持つエンティティ モデルを導入する (つまり汚染する) 設計を避けようとしています。3 番目のテーブル ( EAV モデルの流行の後) にユーザー テーブルとの多対 1 の関係を含めて、複数/可変のユーザー関連フィールドに対応します。

あなたの現在/短期的なニーズが何であるかはわかりませんが、Twitter や linkedIn のユーザーに対応するためにアプリを再設計するのは苦痛かもしれません。facebookUserIdそのような属性テーブルに列の内容を抽象化できる場合

 user_attr{
 id PK
 user_id FK
 login_id
  }

さて、上記の定義は、現在のニーズを処理するには十分にあいまいです。正しく行われた場合、EAV は次のようになります。

 user_attr{
 id PK
 user_id FK
 login_id
 login_id_type FK
 login_id_status //simple boolean flag to set the validity of a given login
  }

は、現在サポートlogin_id_typeされているさまざまなログイン タイプをリストする属性テーブルへの外部キーになります。これにより、既存のシステムを大幅に変更することなく、ユーザーがさまざまな外部サービスを使用して複数のログインを持つことができるという柔軟性が得られます。

于 2012-11-02T05:45:18.220 に答える
1

非常によく似た 2 つのテーブル facebookusers と normalusers が存在することで、警告ベルが大きく鳴り響いています。3型になったらどうする?それとも10分?これは非常識です、

ユーザーのタイプを示す属性列を持つユーザー テーブルが 1 つ必要です。ユーザーはユーザーです。

データ モデルはできる限り単純にしてください。データ構造を介してあまりにも多くのカンフーを構築しないでください。データベースを変更するよりもはるかに簡単に変更できるアプリケーションに任せてください。

于 2012-10-31T23:40:17.853 に答える