ユーザーとユーザープロファイルを異なるテーブルに保持しますか?


26

いくつかのプロジェクトで、開発者が重要なユーザー情報を1つのテーブル(電子メール/ログイン、パスワードハッシュ、スクリーン名)に、残りの重要ではないユーザープロファイルを別のテーブル(作成日、国など)に保持することを好みます。本質的ではないということは、このデータがたまにしか必要ないということです。明らかな利点は、ORMクエリを使用している場合、より少ないフィールドをクエリすることは明らかに良いことです。ただし、同じテーブルに2つのエンティティをマップすることができます。これにより、不要なものを照会する必要がなくなります(より便利になります)。これらのものを2つのテーブルに保持することの他の利点を知っている人はいますか?



1
@MichaelTありがとう!リンクされているすべての質問にコンセンサスがないことは興味深い。
アンドレイ

それが、私が自分で答えようとするのではなく、リンクされた質問のリストを使って行った理由です。それは本当にケースバイケースに帰着し、特定のアプリケーションがどのように設計されています。必要に応じて、いつでもビューを使用して2つのビットをまとめることができます。また、一方のリンクを解除する(アカウントを削除する)可能性を検討しますが、もう一方は保持します(質問はアカウントにリンクする必要がありますが、アカウントには常にプロファイルがありません...)。ソフトウェアエンジニアリングチャットに参加するか、DBA.SEに行ってチャットで質問するのは興味深い質問かもしれません。

1
@MichaelTユーザーモデルを提供する一般的なフレームワークを作成することを考えています。
アンドレイ

過去のいくつかのプロジェクトでは、データベースファイルが破損または破損した場合にプライマリテーブルを保護する目的で、非常に頻繁に書き込まれると予想される列を独自の別のテーブルに意図的に移動しました。
GrandmasterB

回答:


11

プロジェクトのサイズと要件によって異なります。

ユーザーに関するデータを、目的と要件が異なる2つのセットに分割できる1つの方法を見ることができます。

  • 識別データ:ユーザー名、パスワードハッシュ、電子メールアドレス、最終ログイン時刻など
  • ユーザー設定、最新のアクティビティ、ステータスの更新などを含むユーザープロファイルデータ

どちらのカテゴリにも該当するユーザーに関する属性がいくつかあることに注意してください(例:ユーザーの生年月日)。ただし、これら2つのセットの違いは、最初のセットが厳密に制御され、特定のワークフローを介してのみ変更できることです。たとえば、パスワードを変更するには既存のパスワードを入力する必要があり、電子メールを変更するには電子メールの検証が必要な場合があり、ユーザーがパスワードを忘れた場合に使用されます。

設定にはこのようなACLは不要であり、ユーザーが同意する限り、理論的にはユーザーまたは別のアプリケーションによって変更できます。アプリケーションが悪意を持って、またはバグのためにデータを破損したり、データを変更しようとすると、リスクは低くなります(他のセキュリティ対策が講じられていると仮定します)。しかし、通常、ユーザー名、パスワード、または電子メールユーザーの身元を推測したり、サービスを拒否したり、管理者のサポートコストを発生させたりするために使用できるためです。

したがって、通常、データは2種類のシステムに保存されます。

  • 通常、IDデータはディレクトリまたはIAMソリューションに格納されます。
  • 優先データはデータベースに格納されます。

ただし、実際には、人々はこれらのルールに違反し、どちらか一方を使用します(たとえば、ASP.NETメンバーシッププロバイダーの背後にあるSQLサーバー)。

IDデータが大きくなるか、それを使用する組織が大きくなると、さまざまな種類の問題が忍び込みます。たとえば、ディレクトリの場合、マルチサーバー環境のすべてのサーバーにパスワードの変更をすぐに複製しようとします。ただし、ユーザー設定には結果整合性のみが必要です。(FYI:これらは両方ともCAPS定理の異なる最適化です。)

最後に、ディレクトリ(特にonline / cloudディレクトリ)もOAUTHなどのプロトコルを使用して他のリソースのアクセストークンを発行します(たとえば、Facebook、Google、Microsoftアカウント、ADFSを検討してください)。データベースは非常に複雑な結合とクエリ構造をサポートしますが、ディレクトリは必要ありません。

詳細については、IDディレクトリとデータベースのいくつかの検索が役立ちます。

最終的には、サードパーティとの統合(およびそれらが使用しているもの)を含め、シナリオが将来どのようなものになるかが予想されます。プロジェクトが十分に含まれており、ユーザーIDデータを保護し、正しく認証できると確信している場合は、データベースを使用できます。それ以外の場合は、IDディレクトリを調査する価値があります。

DBを使用する場合、IMOは、1つのDBと2つのDBを使用すると、最終的にユーザーとアプリケーションの両方のアクセス制御になります。


3

基本的な属性用の個人テーブルと、1対1の関係を持つ他の属性用の2番目のテーブルが必要な場合、少なくとも3つのケースがあります。

  • 画像のようなBLOBデータ。別のテーブルを使用すると、パフォーマンス上の理由から、たとえば別のテーブルスペースにデータを個別に保存できます。
  • すべての人に適用されないデータ、または特定の役割を果たしている人にのみ適用されるデータ。メインテーブルの一部である場合、多くの行でnullになる列と考えてください。クリニックのデータベースでは、個人テーブル、患者テーブル、メディックテーブルを使用できます。最初のテーブルには基本属性があり、2番目のテーブルには、その人が保険のような患者である場合にのみ関連する属性があります。 3番目の表(その人物が医療関係者の場合)には、医療関係者のみに適用される医療専門分野およびその他のデータがあります。明らかに、メディックは患者になる可能性があります。
  • リモートシステムのエンティティとの関係を具体化するテーブル。この場合、テーブルは、相互運用性の理由から、個別のデータベース内の一意の識別子間の等価性を確立します。

あなたが公開するケースは2番目のケースに収まると思います。


1

それらを分離したままにする主な理由は、オブジェクト指向プログラミングで「神のクラス」として知られているものを避けることです。ORMはテーブルとフィールドをクラスと属性に関連付けます。そのため、SQLレベルとしても重要になります(ORMがなくても、一般に同様の原則があります)。

Userクラス(および関連付けによりuserテーブル)は、多くの場合、数百の属性/フィールド、数十または数百のメソッド、および1000行を超えるクラス定義(メソッド用)を持つgodクラスになります。私はそれをすべて見てきました。一回以上。

したがって、ユーザーの分離はそれに対処しようとします。人、ユーザー、アカウントがあり、懸念の分離は少し人為的に見えるかもしれませんが、複雑さを避け、各オブジェクトがデータの1つの側面のみに関心があることを確認することです。


2
肥大化したユーザークラスでさえ、必ずしも神のクラスではありません。ユーザー関連のロジックで肥大化する可能性があります(大きなプロジェクトでは複雑になる可能性があります)が、無関係なロジックが組み込まれていない場合、大きな問題は発生しません。1つのクラスを2つに分割することで、前述の神のクラスの問題がどのように解決されるかはわかりません。
アンドレイ14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.