これはDBスキーマを構造化するばかげた方法ですか、それとも完全に何か不足していますか?


61

私はリレーショナルデータベースでかなりの作業を行ってきましたが、優れたスキーマ設計の基本概念はかなりよく理解していると思います。私は最近、DBが高給コンサルタントによって設計されたプロジェクトを引き継ぐことを任されました。私の腸の本能-「WTF ??!?」-保証されていますか、それともこの男は私の天才であるかのような天才ですか?

問題のDBは、従業員からのリクエストを入力するために使用される社内アプリです。そのほんの一部を見るだけで、ユーザーに関する情報と、行われているリクエストに関する情報が得られます。私はこれを次のように設計します:

ユーザー表:

UserID (primary Key, indexed, no dupes)
FirstName
LastName
Department

リクエスト表

RequestID (primary Key, indexed, no dupes)
<...> various data fields containing request details
UserID -- foreign key associated with User table

シンプルでしょ?

コンサルタントは次のように設計しました(サンプルデータを使用)。

UsersTable

UserID  FirstName   LastName
234     John        Doe
516     Jane        Doe
123     Foo         Bar

部門テーブル

DepartmentID   Name
1              Sales
2              HR
3              IT

UserDepartmentTable

UserDepartmentID   UserID   Department
1                  234      2
2                  516      2
3                  123      1

RequestTable

RequestID   UserID   <...>
1           516      blah
2           516      blah
3           234      blah

データベース全体はこのように構築され、すべてのデータは独自のテーブルにカプセル化され、数値IDがすべてをリンクしています。コンサルタントはOLAPについて読んでいて、「整数検索の速度」を望んでいたようです。

また、これらすべてのテーブルを相互参照するための多数のストアドプロシージャも持っています。

これは、小規模から中規模のSQL DBに有効な設計ですか?

コメント/回答をありがとう...


12
ああ、これでWTFと言えば、おそらく200行以上のテーブルと1000行を超えるストアドプロシージャを持つテーブルを見たことがないでしょう。
ジョブ

42
恥ずかしいと感じた後に削除しないための+1。他の人が学習できるようにこれを残してくれてありがとう。
ウェインクーツ

2
@Job-実際、私はそうではありません-私は貿易ではDBAではありません(今ではかなり明白です!笑)。そのため、SQL WTFのしきい値はかなり低くなっています。ただし、コンサルタントの設計のポイントを完全に見逃しているため、自分の能力をWTF化できます。あなたはちょうどあなたが愚かなと感じる日がありますか?
ジム

9
@ジム:おめでとうございます、あなたは愚かな日を啓発された日に変えました。
ウェインクールツ

3
これらの高給コンサルタントを呪ってください!
-davidsleeps

回答:


73

私にはぴったりです。これは非常に正規化されているため、他の方法では得られない多くの柔軟性が得られます。正規化されていないデータは苦痛です。


あなたの答えは完全に理にかなっており、私の質問とスキーマを見ると、彼が使用しているテーブルの数だけで混乱しているかもしれません。私は私の質問の例を非常に単純化しましたが、概念がどのように健全であるかがわかります-彼は私がするよりもはるかに多くのものを分割しています。ため息、私はDBAではない良いことだと思います!:)
ジム

10分間のルールで設計することを学んでください:「今では本当のことは、おそらく10分間ではないでしょう。」デザインが変更に対応できることを確認してください。
Blrfl

1
このスキーマには、実際には、従業員が挿入されると、その部門が存在する必要があるという利点があります。
サイモンリヒター

@SimonRichter:それは真実ではありません。従業員は、部門が存在せずに作成できます。また、その逆も可能です。
ダニエル・ディニース

@SimonRichterこの設計の利点は、OPの例とは対照的に、部門が別のエンティティであり、部門と従業員の間に多対多の関係があることです。一対一」(多対一とは言えません。別の部署エンティティが関係と呼ばれることはないため)。
ダニエル・ディニーズ

48

私は、WTFが保証されているとか、その男が狂気の天才的なデザインをしているとは思わない-それはかなり標準的なデータベース正規化です。

部門テーブルを使用する理由は、部門を別のテーブルに配置しない場合、「Sales」、「sales」、「Salesmen」、「Sails」、および「Selling」部門のユーザーを処理する必要があるためです。あなたがそれを防ぐために何かをしない限り。そして、余分なテーブルを持つことは、そのための最良の方法(の一部)です。

UserDepartmentテーブルがあるべきかどうかは、より難しい呼び出しです。これは、もちろん、どちらの決定もうまくいかず、夢中にならないことを意味します。一方では、すべてのテーブルのデザインとロジックがユーザーごとに1つの部署を想定していて、それが変更され、もう何年も何年も理由なく余分な結合を行うことは現実的な可能性であり、痛みでもあります。

個人的には、UserDepartmentテーブルが多すぎると思います。たとえ含まれていても、時間が経つにつれて、部門ごとに1人のユーザーしかいないと想定するクエリを作成する可能性があるため、両方の世界で最悪の結果になります。ユーザーごとに複数の部門が許可されると、とにかくコードが機能しなくなります。

編集-多対多の関係をサポートするかどうかの重要な要因は、ビジネスルールが明確かどうかです。複数の部門のユーザーがどのように機能するかわからない場合、ユーザーが複数の部門にいる場合をコードが正しく処理できない可能性があるため、テーブルを追加しても意味がありません。

念のため、ユーザーごとに多くの部門を許可したと想像してください。次に、部門に基づいて手数料を割り当てるためのビジネスルールを実装しました。その後、複数の部門が許可されました。幸いにも、これを考慮した方法でコミッションコードを書く先見性がありました。残念ながら、両方のユーザーに各部門からのコミッションを追加しました。経営陣は、各販売の人の役割に基づいてほしいと考えました。それで、テーブルを前もって持っていてどれくらい良かったのでしょうか?「万が一のために」持っていた、まったく必要のない他のテーブルについてはどうですか?

後で編集-コンサルタントがこれらすべての中間テーブルを追加したいと考えた別の理由は、このフォローアップの質問で対処されています。 「必要なすべてのテーブルに入れる」アプローチ。


あなたは私のWTFが何であるかを言葉にしたと思います-彼はこれらの中間テーブルのトンを使用しています、そしてそれはちょうど私にはとても愚かに見えました。この質問をもっと小さな例に分解したので、それほど悪いとは思えないので、投稿するのはかなり愚かだと感じます。
ジム

5
多くのコメントからわかるように、「YにつきXは1つしかありません」というコメントについては健全な懐疑論があります。コンサルタントは、「YにつきXが1つしか存在しないのはなぜか」という苦情から身を守っている。そのうちのいくつかはおそらく出てくるでしょう。しかし、彼は多くの結合を持つコードを維持する責任を負いません(それほど悪くはありませんが難しく)、まだ存在しないビジネスルール(悪い)に対して正しい必要があります-「ユーザーはなぜ各部門からの許可、彼らは各許可の最低値を取得する必要があります」など。
psr

@psrタイプミスがあると思います。「部門ごとに1人のユーザーしかいないと想定するクエリ」は「ユーザーが1つの部署にしかいないと想定するクエリ」ではありませんか?
BiAiB

@BiAiB-あなたは正しいです、それは私が言いたいことです。
psr

14

要件がユーザーごとに複数の部門を持つことである場合、この設計は理にかなっています。それについての唯一の不満はあるUserDepartmentTable持つサロゲートキーUserDepartmentIDは必要ありません(ただ作るUserIdDepartmentId複合主キー)。

ユーザーが1つの部署にのみ属している場合、設計は理にかなっています(ただし、部署の参照テーブルはまだ良いことです)。


18
...ユーザーごとに複数の部門が可能になるまで。
Blrfl

1
まさに、@ Blrfl。今日の「これまでにない」は、明日の「最高経営責任者(CEO)であり、大動脈瘤であるため、それはない」ということです。
アダムクロスランド

2
その種の治療に値するものを決定することの一部は、問題領域を理解することです。一部のアプリケーションでは、従業員#3804がアンスミスとアンジョーンズ(結婚後)として会社に知られていることを知っておくことが重要かもしれません。これにより、従業員のテーブルから名前を正規化するのが正解になります。Jimの場合、ブレーカーテーブルを拡張して履歴を保持する価値があるので、AnnがHRからITに移行した場合、彼女に関連付けられた古いリクエストが、それが本当にHRのリクエストであり、ITのリクエストではないことを反映できます。
Blrfl

8
YAGNI-データベースはリファクタリングできます。
-JeffO

2
@ Oded、Entity Frameworkのような一部のORMマッパーは、複合主キーを持つテーブルではうまく機能しません。
maple_shaft

5

一部の要件は、質問では明確ではありません。正しい答えは、顧客が何を望んでいるかに依存します-私があなたなら、これについて顧客に尋ねます:

0-ユーザーと従業員の違いは何ですか?

1-従業員=ユーザーを想定して、従業員が部門を変更した場合はどうなりますか?

2-従業員のグループは1つの要求を行うことができますか?

3-従業員は複数の部門に所属できますか?CEOについてはどうですか

4-要求を行うことを許可されている従業員のサブセットはありますか?

5-従業員レコードが削除された場合、リクエストはどうなりますか(もしあれば)?

6-リクエストを削除できますか?リクエストが破棄された場合の動作(RIによって従業員レコードを削除しないようにしてください)

7-従業員は「同じ」要求を複数回行うことができます(「同じ」を定義)

8-従業員が会社を辞めるときのリクエストの処理方法(リクエストをキャンセルするか、リクエストを削除しますか?)

さらに質問があるかもしれませんが、私のポイントは、ソリューションが厳密な要件とプロジェクトの範囲に依存するということです。それが決定したら、スキーマを直接導出できます。したがって、提示された両方のソリューションが正しい場合があります。


+1これらは、このタイプのスキーマを設計する前に明確にする必要がある素晴らしい質問です。あなたの論理の流れが好きです。

@ Surfer513:素敵なコメントをありがとう。
NoChance

1

高額なコンサルタントが行った方法で結合テーブルを使用することの潜在的な利点のいくつかを明示的に説明する2点のフォームノートを追加したいと思います。

  • 適切にインデックスが付けられた場合(たとえば、UserDepartmentTableが2つの外部キーにインデックスを付ける場合)、外部キーが一意ではないため、このような結合テーブルのパフォーマンスの低下はわずかです。外部キーが一意であることが保証されている場合、私が知っている小さなデータベース理論では、ルックアップUserDepartmentTable.DepartmentUserテーブル内の他の列をルックアップするより「難しい」ことはありません。
  • 結合テーブルを使用すると、ユーザーと部門間の関連付けに関するその他の情報(作成時のタイムスタンプなど)をより柔軟に設定できます。
  • 結合テーブルを使用すると、関連付けをかなり簡単に「バージョン管理」できます(たとえば、ユーザーが部門を変更したときに、UserDepartmentTable.Activefalseのようなインデックスブールフラグをトリガーし、アクティブな新しい関連付けを作成します)。2つのテーブルモデル(ユーザーと部門のみ)で部門の関連付けをバージョン管理することも可能ですが、より難しく、主キーの重複を避けるために、少なくとも1つ以上の列を追加するか、データベースアクロバットを実行する必要があります。
  • これにより、1対多または多対1または多対多の関連付けを簡単に割り当てることができます。

そうは言っても、高給コンサルタントがやったことをしない理由はいくつかあります。

  • 上記の利点はすべて、考えられる将来のニーズを予測するものであり、現在の状況を複雑にします。YAGNIに準拠していません。後で、2つのテーブルモデルから結合テーブルモデルに移行する移行を記述するのは簡単です。ビジネスの必要性が生じたときにそれを行うことができます。その前にそれを行うことは混乱を招く可能性があります。
  • 他の開発者を混乱させます。はい、あなたの身長(コンサルタントの決定を検討している)のWeb開発者への期待は、結合テーブルを理解して認識することですが、それは必要以上に複雑であり、ビジネスニーズがないことを考えると、混乱を引き起こします。

素敵な分析-しかし、私は私の仕事で開発者としての地位を持っているとは言いませんが、db / c#/ vb / etcについて何かを知っいるのは私だけです...デフォルトではtime dev。これはかなり小規模なプロジェクトであるため、コンサルタントのテーブルと参加者の数は「wtf」と言っていました(しかし、皆さんのおかげで私は今「oic ...」と言っています)
ジム

かなり古いトピックですが、まだ関連しています...リファクタリングは非常に難しいかもしれません。将来、1つの部門ではなく複数の部門が必要ですが、UsersにはFKとして部門IDしかありません。最終的には、参照先(Users.DeptIDとUsersDepartmentsTable)が重複するか、Users.DeptIDのコンマ区切りリストやXMLのような完全なガベージになります。YAGNIまたはKISSによって提案されているように、正しいソリューションを簡単に追加することはできませんでしたが、妨げられます。
エリックハート

0

必要な情報の完全な構造がなければ、それがひどいのかどうかは言えません。しかし、少なくとも示されている作品は「WTF」デザインのものではありません。データ構造の3番目の標準形式のように見えます(まあ、理論的には4番目と5番目もあります)。

一部のトークでは、表示されている部分の「自然」キーと「人工」キーの2つの学校間でUserDepartmentTableを配置できます。私が見ることができるように、これ以上何もありません

正規化は、多くの理由のために良いDB-開発者/デザイナーのルールで、* *正規化は主にスピード勝利のための開発の途中で時々使用されています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.