大規模なリレーショナルデータベースを設計する場合、通常の形式から逸脱すること、つまり非正規化を決定することがよくあります。
この理由は、指定されたデータへのアクセスを高速化する試み、使用されるプラットフォーム/フレームワーク/開発ツールの制約、データベース開発者/設計者のスキルの欠如など、さまざまです。
厳密に言えば、フレームワークの制約などへの言及は、実際にはスキルの欠如を正当化する試みです。
非正規化されたデータは脆弱性であり、データベースを一貫性のない(統合されていない)状態にするのは簡単です。
これで何ができるでしょうか?
例
データベースには、いくつかの財務操作の表があります。さまざまなアカウントでの資金の受け取りと処分です。
アカウントの残高を常に知る必要があります。
正規化されたデータでは、ファンドの残高は常に計算値です。借方記入なしで領収書の合計を計算します。
ただし、操作が多い場合は毎回残高を計算するのはコストがかかりすぎます。そのため、実際の残高を別のテーブルに保存することにしました。このテーブルのデータを更新するにはどうすればよいですか?
解決策は「通常どおり」です
私が使用しなければならなかったほとんどすべての情報システムで、このタスクはビジネスロジックを実装した外部アプリケーションによって実行されました。アプリケーションが単純で、ユーザーインターフェイスのフォームからのデータ変更ポイントが1つしかない場合は、幸運です。ただし、さまざまな人やチームによって実行されるインポート、API、サードパーティアプリケーションなどがある場合はどうなりますか?合計が1つではなく複数のテーブルがある場合はどうなりますか?操作を含むテーブルが複数ある場合はどうなりますか?
開発者が操作を更新するときに一連のテーブルを更新したかどうかを監視するのはますます難しくなっています。データの整合性が失われます。口座残高は業務に対応していません。もちろん、テストはそのような状況を明らかにしなければなりません。しかし、私たちの世界は理想的ではありません。
トリガー
別の方法として、トリガーを使用して非正規化データの整合性を制御します。
トリガーはデータベースの速度を大幅に低下させると聞いたので、トリガーを使用しても意味がありません。
2番目の議論は、すべてのロジックが別のアプリケーションにあり、ビジネスロジックを別の場所に保持することは不合理であるというものでした。
理解しましょう。
ラグ
テーブル内のデータを変更するトランザクション内でトリガーが起動します。トリガーが必要な手順を実行するまで、トランザクションを完了できません。したがって、結論は、トリガーは「軽い」ものでなければならないということです。
トリガーの「重い」クエリの例は次のとおりです。
update totals set total = select sum(operations.amount) from operations where operations.account = current_account where totals.account = current_account
クエリは、操作を含むテーブルを参照します 合計金額 アカウントの操作の 。
データベースが増えると、そのようなクエリはますます多くの時間とリソースを消費します。ただし、次のタイプのライトクエリを使用して同じ結果を受け取ることができます:
update totals set total = totals.total + current_amount where totals.account = current_account
新しい行を追加する場合、このトリガーは、計算せずにアカウントごとに合計を増やすだけです。合計は、テーブルのデータ量に依存しません。新しい操作を追加するたびにトリガーが起動することを確認できるため、合計を再度計算することは意味がありません。
行の削除または変更は同じ方法で処理されます。このタイプのトリガーは操作を遅くしませんが、データの結合と整合性を保証します。
トリガーを使用してテーブルにデータを追加するときに「ラグ」が発生するたびに、それはそのような「重い」クエリの例でした。ほとんどの場合、「簡単な」クエリで書き直すことができました。
ビジネスロジック
データの整合性を提供する機能とビジネスロジックを区別する必要があります。いずれの場合も、データが正規化されているかどうかを質問しますが、そのような関数が必要でしょうか?正の場合、関数はビジネスロジックです。負の場合、機能はデータの整合性を提供することです。これらの関数をトリガーにラップできます。
ただし、PostgreSQLやOracleなどのDBMSを介してすべてのビジネスロジックを実装するのは簡単であるという意見があります。
この記事が情報システムのバグの数を減らすのに役立つことを願っています。
もちろん、ここに書かれていることすべてが究極の真実だとは思いません。もちろん、実際の生活では、すべてがはるかに複雑です。したがって、それぞれの特定のケースで決定を下す必要があります。エンジニアリングの考え方を活用してください!
追記
- この記事では、トリガーを強力なツールとして使用することの唯一の側面に注目しました。
- この記事で説明されているアプローチにより、操作でインデックスを回避できます。 テーブル。これにより、このテーブルにデータを追加するプロセスを高速化できます。大量の場合、このアプローチはトリガーに費やされた時間を簡単に補います。
- どのツールを使用する必要があるかを理解することが重要です。この場合、多くの問題を回避できます。