15

私の教授 (長年にわたってシステム開発についてしっかりと理解していると主張していた) と私は、データベースの設計について議論しています。

例として: 私の教授は、この設計が正しいと主張しています: (列のリスト)

Subject_ID
Description
Units_Lec
Units_Lab
Total_Units

等...

合計単位列に注意してください。彼は、この列を含める必要があると述べました。不要であることを説明しようとしました。必要な場合は、単純に 2 つを追加してクエリを作成するだけだからです。

本で見つけた例を彼に見せたのですが、システムを作る上であまり本に頼る必要はないと彼は主張しています。これと同様のケースにも同じことが当てはまります。

student_ID
prelim_grade
midterm_grade
prefinal_grade
average

彼は私に平均を含めることを望んでいました!どこに行っても、これが正規化の違反であると確信させる記事を読んでいる自分に気付くことができます. 平均が必要な場合は、3 つの等級を簡単に計算できます。彼はいくつかのシナリオを列挙しました (「ねえ! クエリが誤って削除されたらどうしますか? どうしますか? そのため、クエリをテーブルに含める必要があります!」)

彼が望むものに準拠するために、データベース (約 40 を超えるテーブルで構成される) を再構築する必要がありますか? 私は間違っていて、これらのことを見落としているだけですか?

もう 1 つのことは、彼が支払いテーブルに合計金額を含めたかったということですが、これは不要だと思います。(製品の単価と数量を計算するだけです。) 彼は、システム全体の管理にとって重要な借方および/または貸方を計算するためにその列が必要であり、トランザクションのバランスをとるために必要であると指摘しました。どう思うか教えてください。

4

7 に答える 7

13

あなたのソリューションがより正規化されていると言うとき、あなたは正しいです。

ただし、クエリのパフォーマンスを向上させるために正規化ルールに故意に違反することを目的とした非正規化(google for it)と呼ばれるものがあります。

たとえば、最初の5つのサブジェクト(何であれ)を、数または合計ユニットの減少順に取得したいとします。

ソリューションでは、2つのテーブル(subjectおよびunit)を完全にスキャンし、結果セットを結合して出力を並べ替える必要があります。

教授のソリューションでは、のインデックスから最初の5つのレコードを取得するだけで済みtotal_unitsます。

もちろん、これには(計算リソースと開発の両方の観点から)保守コストの増加という代償が伴います。

ここで誰が「正しい」かはわかりません。プロジェクト自体、データ量、実行するクエリなどについては何も知りません。これは、すべてのプロジェクトに対して行う必要のある決定です(一部のプロジェクトでは、コア決定)。

問題は、教授がこの要件の論理的根拠を持っているということです。それは正しいかもしれないし、そうでないかもしれません。

なぜ彼があなた自身に上記のすべてを説明しなかったのか、別の質問です。

于 2012-05-26T19:42:34.507 に答える
13

あなたは絶対に正しいです!正規化のルールの 1 つは、他の属性の値を使用して簡単に推測できる属性を削減することです。つまり、何らかの数学的計算を実行することによって。あなたの場合、合計ユニット列は単純に追加するだけで取得できます。

その特定の列を持つことは推移的な依存関係の明らかな兆候を示し、3番目の正規化規則に従って、それらを減らすことが推奨されることを教授に伝えてください。

于 2012-05-26T18:24:22.253 に答える
6

redskins80のすばらしい答えに加えて、これが悪い考えである理由を指摘したいと思います。ソース列の1つを更新する必要があるたびに、計算列も更新する必要があります。これは、バグを簡単に含むことができるより多くの作業です(おそらく、1年後、別のプログラマーがシステムを変更しているとき)。

代わりに計算列を使用できるかもしれませんか?それは実行可能な中間点になります。

編集:非正規化はその場所を持っていますが、それは取るべき最後の手段です。それは化学療法のようなものです。医者はあなたの健康へのさらに大きな脅威を治すためだけにあなたに毒を注入します。これが最後の可能なステップです。

于 2012-05-26T18:37:15.410 に答える
6

私の意見では、質問を見たときに答えが完全ではないため、これを追加することが重要だと思います. 元の質問には適切に回答されていますが、ここに問題があります。したがって、以下に引用されている追加の質問のみを考慮します。

もう1つのことは、彼が支払いテーブルに合計金額を含めたかったことです.これは不要だと思います(製品の単価と数量を計算するだけです.). 彼は、システム管理全体にとって重要な借方および/または貸方を計算するためにその列が必要であり、トランザクションのバランスを取るために必要であると指摘しました。どう思うか教えてください。

この編集は面白い。これがお金を扱う取引システムであるという事実に基づいて、責任を負う必要があります。トランザクション、製品、価格、金額という基本的な用語をいくつか取り上げます。

その意味で、非正規化は非常に一般的であり、必要ですらあります。なんで?説明責任を負う必要があるからです。したがって、トランザクションが登録されると、変更されることはありません。それを修正する必要がある場合は、別の取引を行います。

はい、たとえば製品価格*金額*税などを計算できます。これは、正規化の意味で理にかなっています。ただし、関連するすべてのレコードを完全にロックダウンする必要があります。たとえば、products テーブルを見てみましょう。トランザクションの前に価格を変更した場合、トランザクションが発生したときに考慮に入れる必要があります。ただし、後で価格が変更された場合、取引には影響しません。

そのため、製品が変更される可能性があるため、単に transaction.product_id=products.id に参加することはできません。例:

2012-01-01 price = 10
2012-01-05 price = 20
Transaction happens here, we sell 10 items so 10 * 20 = 200
2012-01-06 price = 22

ここで、2012 年 1 月 10 日のトランザクションを検索するので、次のようにします。

SELECT 
    transactions.amount * products.price AS totalAmount 
FROM transactions 
INNER JOIN products on products.id=transactions.product_id

これは 10 * 22 = 220 となり、正しくありません。

したがって、2 つのオプションがあります。

  1. products テーブルの更新を許可しないでください。したがって、そのテーブルをバージョン管理するため、すべてのレコードに対して、更新ではなく新しい INSERT を追加します。したがって、トランザクションは製品の正しいバージョンを指し続けます。

  2. または、トランザクション テーブルにフィールドを追加するだけです。したがって、トランザクション テーブルに totalAmount を追加し、トランザクションが挿入されたときに (データベース トランザクションで) 計算して保存します。

はい、非正規化されていますが、それには正当な理由があり、説明責任があります。あなたはただ知っており、取引、ロックなどで検証されています.取引が発生した瞬間、価格= 20などの説明された製品に関連しています.

それに加えて、とにかくそれを行う必要がある場合、それは非正規化の良いことです。レポートを実行するのは非常に簡単です。月、年などの総取引額。すべて非常に簡単に計算できます。

正規化には、たとえば、二重ストレージがない、編集ポイントが 1 つであるなどの利点があります。ただし、この場合、トランザクション ログ データベースには許可されておらず、優先されないため、その概念は必要ありません。

トランザクションを、現実世界で起こった何かの登録と見なしてください。それは起こりました、あなたはそれを書き留めました。今は歴史を変えることはできません、それはそのまま書かれました。未来はそれを変えません、それは起こりました。

于 2012-07-13T13:03:01.707 に答える
1

古き良き古典的なリレーショナルモデルを実装したいのであれば、あなたがしていることは正しいと思います。

一般的に、それは実際には哲学の問題です。一部のシステム(例としてOracle)では、オブジェクトを優先して従来のリレーショナルモデルを放棄することもできます。これは、(テーブルに保持される複雑な構造であるため)第1 NFに違反しますが、オブジェクト指向モデルの能力を提供します(継承、オーバーライドメソッドなどを使用できます)。これは、場合によっては非常に優れています。使用される言語は引き続きSQLであり、拡張されているだけです。

私の答えは主題から逸脱していることは知っていますが(まったく新しいデータベースタイプを考慮しているため)、かなり一般的な質問の際に共有するのは興味深いことだと思いました。

実際のアプリケーションのデータベース設計は、どのテーブルを作成するかという問題ではありません。現在、データの保持と処理に関しては、数え切れないほどの可能性があります。私たち全員が知っていて愛しているリレーショナルシステム、オブジェクトデータベース(db4oなど)、オブジェクトリレーショナルデータベース(オブジェクトリレーショナルマッピングと混同しないでください。つまり、オブジェクトを備えたOracle 11gなどのツール)、xmlデータベース(eXistを使用)があります。 、ストリームデータベース(Esperなど)およびMongoDB、Cassandra、CouchDB、Oracle NoSQLなどの現在繁栄しているnoSQLデータベース(データベースと呼ばれるべきではないと主張する人もいます)

これらのいくつかの場合、正規化はその意味を失います。各モデルは完全に異なる目的を果たします。「データベース」という言葉は、以前よりもはるかに広い意味を持っていると思います。

リレーショナルデータベースに関しては、教授ではなくあなたに同意します(ただし、彼に強く反対するのが良い考えかどうかはわかりませんが)。

さて、要点まで。あなたはオープンマインドであり、考慮すべき多くのオプション(彼の見解を含む)があることを理解しているが、状況ではデータを正規化する必要があることを示すことで、彼に勝つかもしれないと思います。

私の答えは、stackoverflowの投稿に対するかなりの良識の流れであることを知っていますが、それが狂気のせせらぎとして受け取られないことを願っています。

関係綱引きで頑張ってください

于 2012-05-26T19:26:04.450 に答える
0

正規化の目的は、冗長性を排除して、主にトランザクション システムで更新の異常を排除することです。リレーショナルは、トランザクション処理、DW、マスター データ、および多くの BI ソリューションにとって、依然として最高のソリューションです。ほとんどの NOSQL の整合性要件は低くなっています。だからあなたは私のつぶやきを失います - 迷惑ですが壊滅的ではありません. しかし、私の百万ドルの株式取引を失うことは大きな問題です. 選択は、NOSQL とリレーショナルではありません。NOSQL は特定のことを非常にうまく実行します。しかし、リレーショナルはどこにも行きません。これは、トランザクションの更新指向のソリューションにとって依然として最良の選択です。データが読み取り専用またはほとんど読み取り専用の場合、正規化の要件を緩和できます。これが、DW では冗長性がそれほど大きな問題ではない理由です。更新はありません。

于 2014-01-14T22:39:49.447 に答える