1

私は現在、多くの企業で使用される Web アプリケーションを設計しています。ただし、データの保存方法を決定するのに問題があります。データの一般的な構造は、次のツリーに示されています: http://i.imgur.com/lpYwqya.png

したがって、すべてのクライアントを一覧表示するテーブルが作成されます。各クライアントには、独自のユーザーとプロジェクトがあります。各プロジェクトには、ユーザーとタスクの 2 つの子があります。ユーザーは、そのプロジェクトへのアクセスを許可されているクライアントの下に登録されているユーザーを指します (そのユーザーの ID とそのアクセス許可 [読み取り/書き込み] を格納します)。ツリーの各レベルについて、データを格納する必要があります。たとえば、タスクには次のフィールドがあります (WBS、名前、開始日、終了日、期間、作業、コスト、固定費、ベンダーなど)。

データを最適に構造化する方法を決定するのに苦労しています。データは常にツリーの一番上から (親から子へ) アクセスされるので、子の間を移動したり、ツリーをバックアップしたりする必要はありません。ここに私が思いついた2つの解決策があります:

解決策 1 : テーブルの数に制限はありません。クライアントが作成されるたびに、1_projects と 1_users の 2 つのテーブルも作成されます (1 は最初のテーブルのクライアントの ID です)。プロジェクトが作成されると、テーブル 1_1_tasks が作成されます。したがって、ID 5、タスク ID 3895、プロジェクト ID 19、クライアント ID 57658 のリスクのプラン テーブルは、57658_19_3895_5_plans になります。

解決策 2 : クライアント、ユーザー、プロジェクト、project_users、tasks、risks、risk_updates、plans、plan_updates の 9 つのテーブルを用意します。リスク テーブルには、すべてのリスクが関連付けられているフィールドに加えて、client_id、project_id、task_id も含まれます。したがって、たとえば、クライアントが特定のタスクに対して持っているすべてのリスクを返したい場合は、ツリー全体で client_id = #、project_id = #、task_id = # のリスクを検索します。もちろん、これらのフィールドはリスク テーブルの複合/複合キーを形成します。したがって、リスク テーブルには、すべてのタスク、すべてのプロジェクト、すべてのクライアントのリスクが格納されます。最後のテーブル plan_updates は明らかに巨大です。

同じ親に属していないノードは同じテーブルに格納されないため、ツリーを簡単に下に移動できるため、ソリューション 1 は強力であると思います。ただし、このソリューションも非常に悪いものです。膨大な数のテーブルが存在するため、後でデータベースを変更することが非常に困難になるからです。

ソリューション 2 は、すべてのリスクが 1 つのテーブルに集中しているため強力です。ただし、すべての親要素の id に一致するフィールドをテーブル全体 (大規模になる) で検索する必要があるため、plan_updates テーブルなどを検索するときに非常に非効率になるのではないかと思います。

これをすべて大局的に見ると、次のことが予想されます。

ユーザー: クライアントごとに 1 ~ 20 人。通常は 5 未満です。

プロジェクト: クライアントごとに 1 ~ 100。ほとんどが20以下になります。

タスク: プロジェクトごとに 100 ~ 10,000。

リスク: タスクごとに 0 ~ 10。ただし、タスクの約 30% のみにリスクがあり、これらの大部分には 1 ~ 4 個のリスクしかありません。

リスクの更新: リスクごとに 1 ~ 10。

計画: リスクごとに 1 ~ 5。

プランの更新: プランごとに 1 ~ 10 回。

この問題をどのように解決するのが最善かについて誰かが光を当てることができれば、それは非常に役に立ちます。

4

2 に答える 2

1

2番目の解決策は、私にははるかに合理的です。最初のソリューションの最大の欠点は、構造全体の管理性が悪いことです。すぐに膨大な数のテーブルが作成され、構造が変更された場合 (追加のフィールドまたは追加の制約を追加する必要があります)、問題が発生します。

一方、複合キーに対するあなたの懸念はそれほど深刻ではありません。

たとえば、タスクは個々のプロジェクトに単独で割り当てることができます。クライアントへの直接参照も必要ありません。一方、特定のタスクを誰が実行するかを定義するために、ある時点で、ユーザーとタスクを直接接続する別の nn リンク テーブルを導入する可能性が非常に高くなります。

そのため、タスクのすべてのリスクを一覧表示する場合は、最初にタスクを見つけてから、1 つのキー (タスク ID) を使用してリスク テーブルをスキャンする必要があります。これは、テーブルが 1 つでも複数でも同じです。

解決策 2 を選択し、関連する主キーとインデックス (および該当する場合は一意の列) をすべて特定することを強くお勧めします。これにより、データベースが高速かつ効率的になります。

編集

@MSWが言及しているように、この件についてはもっと多くのことが言われています。この主題をカバーするデータベース設計 (正規性、原子性などの原則を含む) に関する文献は無限にあります。

解決策 1 の質の低さを説明するもう 1 つのポイントは、プロジェクトがすべて多数の異なるテーブルにあるため、後でさまざまなプロジェクトにわたって簡単に分析を行うことができないということです。

于 2013-08-14T05:37:44.260 に答える