48

スタック オーバーフローで正規化が広く議論されていることは知っています。以前の議論の多くを読みました。ただし、いくつか追加の質問があります。

少なくとも 100 個のテーブルを持つレガシー システムで作業しています。データベースには、正規化されていない構造、さまざまな異種データを含むテーブル、およびその他の問題があります。私はそれを改善しようとする任務を与えられました。やり直すことはできませんが、既存のスキーマを変更する必要があります。

これまで、私は常に正規化されたデータベースの設計を試みてきました。今質問。上級開発者は、場合によっては正規化できないことを示唆しています。

  1. 時系列データあり。たとえば、製品にリンクする請求書が作成されます。顧客が 1 年後にこの請求書のコピーを要求した場合、元の正確なコピーを作成できなければなりません。製品の価格、名前、または説明が更新された場合はどうなりますか? 年配の男性は、価格やその他の製品情報を請求書テーブルにコピーするよう提案しました。時間の経過に伴う価格の変化を追跡できるように、日付フィールドを持つ productPrice などの別のテーブルを作成する必要があるのではないかと考えています。製品の説明と名前にも同じものが必要でしょうか?複雑そうです。どう思いますか?

  2. データベースは会計システムです。私は会計にあまり詳しくありません。現在、いくつかの要約データが取得され、データベースに保存されています。たとえば、年間の総売上。私のシニア アソシエイトは、会計士は、この値を請求書などから実際に計算されたデータと比較して、アプリケーションが正しく機能していることを確信できるようにすることで、物事が正しいことを確認するのが好きだと言いました。

たとえば、合計が同じではないため、誰かが昨年の請求書を誤って削除したかどうかを現時点で判断できると彼は言いました。彼はまた、これらの合計をその場で計算するのは非常に遅くなる可能性があることも指摘しました。もちろん、データは重複してはならず、必要に応じて常に計算する必要があると言いました。私は、これらのレポートを夜間に生成してキャッシュする SQL Reporting Services またはその他のソリューションを使用することを提案しました。とにかく彼は納得していません。これについて何かコメントはありますか?

4

9 に答える 9

50

あなたの先輩は開発者であり、データモデラーではありません。それらなしで、最初から始める方が良いです。正規化は、本を読まない人だけが複雑になります。彼があなたに考えさせるのは十分に公平ですが、いくつかの問題はばかげています。

あなたの番号:

  1. 実際のオンラインデータと過去のデータの違いを理解する必要があります。次に、単に歴史的なニーズとアーカイブのニーズの違い。それらはすべて特定のビジネス要件に対して正しいものであり、他のすべてのものにとっては間違っています。普遍的な正しいことも間違っていることもありません。

    • 請求書の紙ベースのコピーがないのはなぜですか?法的および税務上の要件となるほとんどの国では、古い請求書を釣り上げることの難しさは正確には何ですか?
    • データベースにクローズされた請求書を保存する要件がある場合、請求書がクローズされるとすぐに、その情報をキャプチャする方法が必要になります。
    • ProductPrice(実際には、私はそれを呼ぶでしょうProductDate)は良い考えですが、必要ではないかもしれません。しかし、あなたは正しいです。データベース全体の完全なコンテキストで、データの最新性を評価する必要があります。
    • 製品価格を請求書テーブルにコピーすることがどのように役立つかわかりません(広告申込情報が多くありませんか?)
    • 請求書のコピーを逆流させる必要がある最新のデータベースでは、閉じた請求書はさらに別の形式(XMLなど)で保存されます。1人の顧客がPDFをBLOBとして保存します。したがって、5年前の製品価格をいじることはありません。ただし、基本的な請求書データは、閉じた請求書の場合でもオンラインで最新のものです。現在の価格を使用して古代の請求書を再計算することはできません。
    • archive_invoiceテーブルを使用する人もいますが、すべてのコードセグメントまたはユーザーレポートツールが2つの場所を調べる必要があるため、問題があります(最近、一部のユーザーはほとんどの開発者よりもデータベースをよく理解していることに注意してください)
  • とにかく、あなたの理解のために、それはすべての議論です。さて、技術的な目的のために。
    • データベースは、1セットのテーブル(「アーカイブ」テーブルなし)から現在およびアーカイブの目的を果たします。
    • 請求書が作成されると、それは法的文書であり、変更または削除することはできません(負の値の新しい請求書によって取り消すか、部分的に貸方記入することができます)。それらはマークされていますIsIssued/IsPaid/Etc
    • Products削除することはできません、マークすることができますIsObsolete
    • InvoiceHeaderとInvoiceItemには別々のテーブルがあります
    • InvoiceItemとの両方にFKがInvoiceHeaderありますProduct
    • 多くの理由で(あなたが言及した理由だけでなく)、InvoiceItem行には。が含まれていNumUnits; ProductPrice; TaxAmount; ExtendedPriceます。確かに、これは「非正規化」のように見えますが、価格や税率などが変更される可能性があるため、そうではありません。しかし、もっと重要なのは、法的要件は、古い請求書をオンデマンドで複製できることです。
    • (紙のファイルから複製できる場合、これは必須ではありません)
    • これは、InvoiceItemsInvoiceTotalAmountの派生列です。SUM()
  1. それはゴミです。会計システム、そして会計士はそのように「働く」ことはありません。

    • それが真の会計システムである場合、JournalEntries、つまり「複式簿記」があります。これは、資格のあるアカウントが(法律により)使用するために必要なものです。

    • 複式簿記は、重複したエントリを意味するものではありません。これは、すべての金融取引(1つの金額)に、それが適用されるソースアカウントとターゲットアカウントが必要であることを意味します。したがって、「非正規化」や重複はありません。銀行データベースでは、金融取引は単一のアカウントに対するものであるため、通常、1つのDbトランザクション内の2つの別個の金融取引(行)としてレンダリングされます。通常の商用データベースの制約は、すべての金融取引に2つの「側面」があることを保証するために使用されます。

    • 請求書が削除できないようにすることは、セキュリティなどとは別の問題です。データベースから削除されるものについて誰かが妄想的であり、データベースが有資格者によって保護されていない場合、彼らはさらに多くのさまざまな問題を抱えています。この質問とは何の関係もありません。セキュリティ監査を取得し、彼らがあなたに言うことは何でもします。

    • ウィキペディアは、正規化は言うまでもなく、技術的な主題に関する信頼できる情報源ではありません。

    • 正規化されたデータベースは、常に正規化されていないデータベースよりもはるかに高速です
      。したがって、正規化と非正規化とは何か、そうでないものを理解することは非常に重要です。人々が流動的でアマチュアの「定義」を持っている場合、プロセスは大きく妨げられ、混乱と時間の無駄な「議論」につながるだけです。定義を修正したら、それをすべて回避して、仕事に取り掛かることができます。

    • 要約テーブルは、時間と処理能力を節約するために、変更されない情報を再計算するために非常に正常です。たとえば、次のようになります。今年のMTDの合計は毎月ですが、今月はそうではありません。(a)情報が非常に大きく、(b)変更されない場合、データの「常に再計算」は少しばかげています。今月のみ計算する

      • 銀行システム(1日あたり数百万の取引)では、EndOfDayで、日次合計も計算して保存します。監査人が変更を加えているため、これらは過去5日間上書きされ、過去5日間の金融取引に対するJournalEntriesは許可されます。
      • 非銀行システムは通常、1日の合計を必要としません
    • 要約表は「非正規化」ではありません(魔法の絶え間なく変化する流動的な「ソース」から「正規化」について学んだばかりの人、または単純な白黒のルールを適用する非実践者の目は除きます)。すべてに)。繰り返しますが、定義はここでは議論されていません。サマリーテーブルには適用されません。

    • サマリーテーブルはデータの整合性に影響を与えません(もちろん、サマリーテーブルのソースとなったデータが不可欠であると想定しています)。

    • サマリーテーブルは現在のデータへの追加であり、現在のデータと同じ制約を持つ必要はありません。現在のデータテーブルとは対照的に、基本的にレポートテーブルまたはデータウェアハウステーブルがあります。

    • サマリーテーブルに関連する更新異常(厳密な定義)はありません。昨年の請求書を変更または削除することはできません。更新異常は、真の非正規化または非正規化の現在のデータに適用されます。


コメントへの回答

だから、アーカイブの権利のために非正規化を行っても大丈夫ですか?

上記の私の説明は十分に明確ではないようです。例を見て、オプションを比較してみましょう。

フー

フー

フー

だから、いや。アーカイブは恐ろしいオプションです(私は何千ものアーカイブされたテーブルを自宅に戻し、インデックスを修正し、通常のパフォーマンスを復元しSELECT、2つではなく1つのテーブルだけをクエリするように戻しました)。しかし、アーカイブを行う場合、それは非正規化されておらず、さらに悪いことに、コピーです。

フー

断然最高のオプション。繰り返しになりますが、これは単純なバージョンであり、完全なバージョンでは、コッドのリレーショナルモデル(批判者によって販売される絶えず変化するナンセンスではない)の時間的定義とSQL準拠のプラットフォームを理解する必要があります。


「正規化されたデータベースは常に正規化されていないデータベースよりもはるかに高速である」という声明には強く反対します。「常に」の使用をハープしなくても、それは明らかに誤りです。データベースの選択的でコヒーレントな非正規化により、パフォーマンスが大幅に向上するシナリオは数多くあります。

[正当化された非正規化の例]:複雑なビジネスの月末の要約のように、日付が制限されたデータセットの複雑な結合。データが1か月の間に収集された場合。その後、永遠に安定します。頻繁に照会されます—マテリアライズド・ビュー、トリガー、またはより高度な方法で事前計算することは理にかなっています。

明らかに、明確な定義が必要です。

  • 正規化


    • 重複データを(単に減らすだけでなく)排除する目的
      複雑な結合はなく、通常の単純な結合だけであることに注意してください。
    • メソッド
      正式なリレーショナルデータモデリング
      (番号でNFをステップスルーしない)。
  • 正規化されていない正常化の
    失敗。データベースに更新異常が残り、トランザクションが混乱します。

  • 非正規化正式な正規化の後、パフォーマンス上の理由から、選択したテーブルに
    1つ以上の列が追加で配置されます。

    • 例えば。「SQL」のふりをして、通常のクエリを許容可能な速度で実行しません。
    • 貧弱なデータベースを置き換えてから40年以上にわたって、非正規化されていると宣言されたすべてのデータベースは、実際には非正規化されていることに注意してください。
  • 要約表/マテリアライズド・ビュー
    上記の回答(もう一度お読みください)で詳しく説明されているように、また「現在のみ」の図に示されているように、履歴の要約値を提供する目的で使用される追加の表であり、変更されません。これは一般的です。  

    • 重複する列はありません。「非正規化」として分類することはできません。

正規化と非正規化に関連する私のステートメント[正規化データベースは常に非正規化データベースよりもはるかに高速です]に同意しませんでした。要約テーブルを「非正規化」として誤って分類していました。


データベースが受け取る複雑で時間のかかるクエリを事前に知っている場合は、それらのクエリの結果を事前に計算できます。たとえば、14テーブルの結合を、必要なデータがすでに含まれているテーブルに置き換えます。

それはまた違う。その2つの一般的な理由は次のとおりです。

  1. データベースはそもそも正規化されていないため、大きなテーブルに対するクエリは低速です
    • 適切な治療法は、適切に正規化することです
  2. あなたのふり「SQL」はとても遅い
    • そのための適切な治療法は、本物のSQLプラットフォームを入手することです。

遅いクエリを処理するために追加のファイル(またはマテリアライズドビュー)を作成する必要があるようなものです。はい、それは非正規化であり、大規模ですが、さらに悪いことに、それらのフィールドの100%コピーです。

于 2010-11-30T02:52:15.273 に答える
12

1) これはアーカイブです。その中にあるものはすべて更新されるべきではありません。私は先輩の提案に従い、その請求書テーブルを自己完結型にします。おそらく、マークアップ言語を含む請求書自体に BLOB を使用しますか?

2) レポート サービス、トリガー更新されるウェアハウス テーブル、いつでもスクリプトで作成するもの... これらはすべて問題ないと思います。正規化することは確かに理想的ですが、常に高速であるとは限りません。私が管理している適切なサイズのヘルスケア データベースは、完全に正規化されています...そして、ロールアップされた方程式と一般的にプルされるフィールドを含む一連の非正規化テーブルがあります。ほとんどすべてが非正規化されたセットから実行されます。100,000 レコードのレポートを確認するたびにさまざまなテーブルからプルし続けるよりも、ファイルがロードされたときにトリガーを使用してこれらに追加する方が高速です。

于 2010-11-29T05:39:37.407 に答える
8

有効なポイントを上げますが、正規化とその意味について完全には明確ではありません。たとえば、

1) 請求書をそのままにしておくとデータが非正規化されるという主張は、完全に完全に間違っています。価格を例に取りましょう。価格の履歴を保持する必要があるというビジネス要件がある場合、現在の価格のみを保持することは間違っており、要件に違反します。そしてそれは正規化とは何の関係もなく、単純にうまく設計されていません。非正規化とは、モデル (およびその他のアーティファクト) にあいまいさの可能性を導入することです。この場合、問題空間を適切にモデル化していません。
テンポラル データをサポートするためにデータベースをモデル化すること (または、バージョン管理および/またはデータベースの領域をアーカイブ/テンポラルおよびワーキング セットに分離すること) に問題はありません。

セマンティクス (要件の観点から) を検討せずに正規化を検討することはできません。

また、上級開発者が違いがわからない場合は、RDBMS 開発の経験がなかったと思います ;)

2) 2 番目の部分は確かに非正規化です。ただし、正規化を真剣に説くシニア DB アナリストに出くわした場合は、意識的に非正規化を行い、太りすぎの欠乏症に利益をもたらし、異常があなたを噛まないことを確認する限り、非正規化は完全に受け入れられると彼/彼女が言うのを聞くでしょう. また、論理モデルを正規化すること、および物理モデルでは、さまざまな目的 (パフォーマンス、メンテナンスなど) のために理想から逸脱することが許可されていることも伝えられます。私の本では、正規化の主な目的は、隠れた異常がないようにすることです (たとえば、 5NFに関するこの記事を参照してください)。

中間結果のキャッシングは、正規化されたデータベースでも、正規化の最大のエバンジェリストによっても許可されています-アプリケーションレイヤーで(ある種のキャッシュとして)行うことも、データベースレベルで行うことも、データウェアハウスを使用することもできますそのような目的。これらはすべて有効な選択であり、論理モデルの正規化とは関係ありません。

また、あなたの会計士については、彼が主張していることは良いテストではないことを彼に納得させ、ユーザーの介入なしにシステムのテストを自動化し、あなたにシステムにバグがないという確信が高まります。

一方で、実際の行を入力する前または後に請求書に行数を入力するなど、入力が完了していることを確認するために、ユーザーが重複した情報を入力する必要があるシステムを知っています。このデータは「複製」されており、入力を検証する手順がある場合は保存する必要はありません。その手順が後で来る場合は、「非正規化」データを格納することが許可されます-再び、セマンティクスはそれを正当化し、モデルを正規化されたものとして見ることができます。(この概念に頭を包み込むことは有益です)

編集: (2) の「非正規化」という用語は、正規形の正式な定義を見て、設計が正規形のいずれかを破る場合に非正規化されていると見なす場合は正しくありません (一部の人にとっては、これは明らかであり、それについての別の方法)。

それでも、多くの人が、必要のない無用なテキストではなく、データベースの冗長性を減らそうとするあらゆる努力に対して正規化という用語を使用するという考えに慣れたいと思うかもしれません (例として、次のような科学論文を見つけることができます)。派生属性を非正規化の形式と呼ぶのが一般的であるという警告として、それらが正しいに違いないとは言いません。ここを参照してください)。

より首尾一貫した認知された権威に言及したい場合 (すべての人に認知されているわけではありません)、おそらく CJDate の言葉で明確に区別できます。

設計理論の多くは、冗長性の削減に関係しています。正規化はrelvar内の冗長性を減らし、直交性はrelvar全体で冗長性を減らします。

データベースの詳細から引用: 実践者のためのリレーショナル理論

そして次のページで

完全に正規化しないと冗長性が生じ、特定の異常が発生する可能性があるのと同様に、直交性を順守しない場合も同様です。

したがって、relvar 間の冗長性の適切な用語は直交性です (基本的に、すべての正規形は単一の relvar について話しているため、正規化を厳密に見ても、2 つの異なる relvar 間の依存関係による改善を示唆することはありません)。

いずれにせよ、データベース設計を検討する際のその他の重要な概念の 1 つは、論理データベース モデルと物理データベース モデルの違いです。小計やインデックスを含むテーブルなど、物理レベルで役立つ多くのものは、モデル化しようとしている概念間の関係を確立して調査しようとする論理モデルには存在しません。だからこそ、それらは許容され、デザインを損なうものではないと言えます。

論理モデルと物理モデルの線が少しぼやけている場合があります。特に良い例は、小計を含むテーブルです。それを物理的な実装の一部と見なし、論理レベルで無視するには、次のことを行う必要があります。

  • ユーザー (およびアプリケーション) が述語と一致しない方法で小計テーブルを直接更新できないようにする (つまり、小計手順にバグがある)
  • ユーザー (およびアプリケーション) が、小計を更新せずにこれらが依存するテーブルを更新できないようにする (つまり、一部のアプリケーションは、合計を更新せずに詳細テーブルから行を削除しない)

上記のルールのいずれかを破ると、一貫性のない事実を提供する一貫性のないデータベースになってしまいます。(このような場合、発生した問題を修正または調査するための手順を正式に設計したい場合は、それを単なる追加のテーブルとは見なさず、論理レベルに存在するべきではありません)。

また、正規化は常に、モデル化しようとしているセマンティクスとビジネス ルールに依存します。たとえば、DBAPerformance はTaxAmount、トランザクション テーブルに を格納することは非正規化された設計ではない例を示していますが、モデル化しようとしているシステムの種類に依存することについて言及していません (それは明白ですか?)。たとえば、トランザクションに と呼ばれる別の属性がある場合、TaxRate通常は非正規化されます。これは、一連の非キー属性 (TaxAmount = Amount * TaxRate => FD: Amount,TaxRate -> TaxAmount) に機能的な依存関係があり、これらのうちの 1 つが必要なためです。削除されるか、一貫性が保証されます。

明らかに、あなたが構築しているシステムが監査会社向けである場合、機能的な依存関係がない可能性があります。彼らは、手計算を使用している、ソフトウェアに欠陥がある、または不完全なデータを記録する能力が必要な人を監査している可能性があります。計算自体が間違っている可能性もあり、監査法人としてその事実をありのままに記録しなければなりません。

したがって、要件によって決定されるセマンティクス (述語) は、関数の依存関係に影響を与えることによって、通常の形式のいずれかが壊れているかどうかに影響を与えます (言い換えれば、関数の依存関係を正しく確立することは、正規化されたデータベースを目指す場合のモデリングの非常に重要な部分です)。

于 2010-11-29T10:31:21.930 に答える
5

あなたの上級開発者は非常に有効な点を指摘しています。私は、履歴データを非正規化しないシステムにサービスを提供することで、これらを自分自身で難しい方法で学びました。

ある意味では、実際にはデータベースにオーバーヘッドを追加していません。データベース内の既存のデータから請求書テーブルを作成しています。請求書は、ある時点でのスナップショットです。その請求書を作成するために必要な情報を非正規化すると、レポート作成がはるかに簡単になります。新しいレポートを作成する必要があり、迅速に作成する必要がある場合は、非正規化を高く評価します。

データベースに合計があるという点で。以前、アプリケーションに変更を加えて数値が同じように加算されなかったときに、これでお尻が救われました (思ったほど難しくはありません)。実際のアプリケーションでは、合計は不一致を修正するために戻るべき明確な場所を与えてくれました。これについては以前に書いたことがあります。ここで読むことができます: http://jlrand.com/?p=95

于 2011-02-01T18:13:14.533 に答える
5

(1)についてはあなたの先輩に賛成です。トランザクション テーブルの行は、トランザクションの時点での状態全体をキャプチャする必要があります。限目。あなたが提案していることは実際のデータを記録していないため、受け入れられません。(2)については私も同意見です。クロスチェックによってビジネスが必要とするものは何でも、実装する必要があります。会計はクロスチェック、複式簿記、帳簿の巻き上げなどを基本としており、それをしなければなりません。これは非常に基本的なことなので、ビジネス要件を実装するのと同じように、非正規化と見なすことさえできません。

于 2010-11-29T05:48:04.383 に答える
5

1) 非正規化を必要としません。必要な各変更の詳細レベルを決定し、適切なキーでそれを保持するだけです。

2) 非正規化とは何の関係もありません。要約データを保管しても、データベースは非正規化されません。非キー属性から派生した結果を同じテーブルに格納することは非正規化の例ですが、それはあなたがここで話していることではないようです。

于 2010-11-29T10:32:33.430 に答える
1

#1の場合

請求書は、売上と支払いから計算する必要があります。価格/製品/割引/送料などの詳細な販売データがない場合は、そこから始めてください。

#2の場合

会計システムを最初からデータベースに書き込むことは大きなプロジェクトです。システムの精度を測定できるように、会計士にビジネスルールを提供してもらうようにしてください。最後に必要なのは、CFOがDBAミーティングに参加し、DBが顧客に過大請求していることを発表することです。さらに悪いことに、過小請求して会社を廃業に追い込んでいます。

SQL Serverを使用している場合は、AdventureWorksデータベースを確認してください。MSが嫌いな場合は、Adventure Worksを見て、そのようにしないでください。

于 2010-11-30T00:02:33.563 に答える
0

データベースの正規化により、重複が削除され、データ更新のための sql クエリがより効率的になります (その他の改善も得られます)。

ただし、ほとんどのクエリがデータの選択に使用され、選択クエリが一度に複数のテーブルに接続する場合は、これらのテーブルの非正規化を検討できます。これにより、データに必要なディスク容量が増加し、SQL 更新クエリの実行に時間がかかりますが、選択クエリが改善されます。

于 2010-11-29T05:52:12.360 に答える
0

データ ウェアハウスを作成する必要があるかどうかを検討しているようです。履歴レポートの目的でデータベースを非正規化しないでください。アーカイブを作成してデータ ウェアハウスに情報を保存すると、ほとんどの情報が非正規化され、データ履歴が維持されます。

于 2016-08-05T23:48:00.643 に答える