トリガーと制約のパフォーマンスに関する考慮事項
-
02-07-2019 - |
質問
データベース内のトリガーまたは制約でビジネスクリティカルロジックを使用する必要があるかどうかを確認しようとしています。
これまでのところ、次に起こることを制御でき、おそらくユーザーを混乱させるエラーの代わりにカスタムユーザーメッセージを提供できるため、トリガーにロジックを追加しました。
トリガーに対する制約を使用することで顕著なパフォーマンスの向上があり、使用するものを決定するためのベストプラクティスは何ですか。
解決
制約が伝わる!
-
制約を使用して、リレーショナル原則、つまりデータに関する事実を指定します。何らかの事実(つまり、新しい要件)が変更されない限り、制約を変更する必要はありません。
-
トリガーを使用して、データの処理方法(挿入、更新など)を指定します。これは「非リレーショナル」です。物事を行う方法。
類推で自分自身をより良く説明するには:SQLクエリを記述する適切な方法は、「欲しいもの」を指定することです; 「取得方法」の代わりに– RDBMSに最適な方法を見つけてもらいましょう。同じことがここでも当てはまります。トリガーを使用する場合、実行順序やカスケードなどのさまざまなことを覚えておく必要があります。可能であれば、SQLに制約を与えてください。
それは、トリガーに用途がないと言っているわけではありません。制約を使用して、データに関する事実を指定できない場合があります。しかし、それは非常にまれです。もしそれがあなたにたくさん起こったら、おそらくスキーマに何らかの問題があります。
他のヒント
ベストプラクティス:制約を使用して実行できる場合は、制約を使用します。
トリガーは、正しく使用されていれば信用を落とすほど悪くはありませんが、可能な限り常に制約を使用します。 最新のRDMSでは、トリガーのパフォーマンスオーバーヘッドは制約に匹敵します(もちろん、だれかがトリガーに恐ろしいコードを配置できないというわけではありません!)
場合によっては、トリガーを使用して「複雑な」制約を実施する必要があります。たとえば、テーブルの2つの外部キーフィールドのうち1つだけを入力したいという状況などです(いくつかのドメインでこの状況を見てきました)モデル)。
ビジネスロジックをDBではなくアプリケーションに配置するかどうかの議論は、環境にある程度依存します。 DBにアクセスするアプリケーションが多数ある場合、制約とトリガーの両方がデータが正しいことを最終的に保護できます。
トリガーはパフォーマンスの問題を引き起こす可能性があります。ほぼ同じ時期に、メンテナンスの悪夢にもなりました。何が起こっているのかわからないおよび(ボーナス!)アプリケーションが「スプリアス」で不規則に動作する;データの問題。 [本当に、それらはトリガーの問題です。]
エンドユーザーがSQLに直接触れることはありません。彼らはアプリケーションプログラムを使用します。アプリケーションプログラムには、トリガーよりもはるかにスマートで保守しやすい方法でビジネスロジックが含まれています。アプリケーションロジックをアプリケーションプログラムに配置します。データベースにデータを入れます。
あなたとあなたの「ユーザー」を除いて共通の言語を共有しないでください。制約違反を説明できます。代わりの方法-説明ではありません-単純なデータベースは、データとアプリケーションコードを維持不可能な泥沼に圧縮するため、問題に変わります。
"すべての人がデータモデルを正しく使用していることを完全に保証するにはどうすればよいですか?"
2つの(そして半分の)テクニック。
-
モデルが正しいであることを確認します。実際の問題領域と一致します。ハッキングや回避策、ショートカットは、複雑な手を振る説明、ストアドプロシージャ、トリガーによってのみ解決できます。
-
アプリケーションのビジネスモデルレイヤーの定義を支援します。全員が共有して再利用するアプリケーションコードの層。
a。また、モデル層が人々のニーズを満たしていることを確認してください。モデルレイヤーに適切なメソッドとコレクションがある場合、基になるデータに直接アクセスするためにモデルレイヤーをバイパスするインセンティブは少なくなります。一般的に、モデルが正しい場合、これは深刻な問題ではありません。
トリガーは、発生するのを待っている大破です。制約はありません。
制約を使用する他の理由に加えて、Oracleオプティマイザーは制約を有利に使用できます。
たとえば、(Amount> = 0)
という制約がある場合、 WHERE(Amount = -5)
でクエリすると、Oracleはすぐにそのことを認識します一致する行はありません。
制約とトリガーは2つの異なる目的のためのものです。制約は、データのドメイン(有効な入力)を制約するために使用されます。たとえば、SSNはchar(9)として格納されますが、制約は[0-9] [0-9] [0-9] [0-9] [0-9] [0-9] [ 0-9] [0-9] [0-9](すべて数値)。
トリガーは、データベースでビジネスを強化する方法です論理。 SSNを再度取得すると、おそらくSSNが変更されるたびに監査証跡を維持する必要があります。これはトリガーを使用して行われます
一般に、最新のRDBMSのデータ整合性の問題は、制約のいくつかのバリエーションで処理できます。ただし、不適切な正規化(または要件の変更、結果として不適切な正規化)が制約を妨げる状況に陥ることがあります。その場合、トリガーは制約を強制できる場合がありますが、RDBMSからは見えないため、最適化には使用できません。また、「非表示」です。ロジック、およびメンテナンスの問題になる可能性があります。スキーマをリファクタリングするか、トリガーを使用するかを決定することは、その時点での判断の呼び出しです。
一般的に言えば、私は制約を好むでしょうし、私のコードはsqlサーバーのエラーをキャッチし、ユーザーによりわかりやすいものを提示します。
@onedaywhen
クエリをSQL Serverの制約として使用できます。スカラー関数に適合させることができます。 http://www.eggheadcafe.com/software/aspnet/30056435/check-contraints-and-tsql.aspx
@Mark Brackett:"制約はドメインを制約するために使用されます...トリガーはビジネスロジックを実施する方法です '':SQL Serverでは、制約の機能が制限されているため、それほど単純ではありません。まだ完全なSQL-92ではありません。テンポラルデータベーステーブルのシーケンス化された「プライマリキー」の古典的な例を考えてみましょう。理想的には、サブクエリでCHECK制約を使用して同じエンティティの期間の重複を防ぎますが、SQL Serverではできません。引き金。また、SQL Serverには、制約のチェックを延期するSQL-92機能がありませんが、代わりにすべてのSQLステートメントの後に(事実上)チェックされるため、SQL Serverの制限を回避するためにトリガーが必要になる場合があります。
可能な限り制約を使用します。彼らはわずかに速くなる傾向があります。トリガーは、制約で処理できない複雑なロジックに使用する必要があります。トリガーの作成もトリッキーであり、トリガーを作成する必要がある場合は、トリガーが挿入、更新、または削除全体に対して動作するため、必ずセットベースのステートメントを使用してください(複数のレコードが影響を受ける場合があります。その上!)、一度に1つのレコードだけではありません。回避できる場合は、トリガーでカーソルを使用しないでください。
トリガーまたは制約の代わりにロジックをアプリケーションに配置するかどうか。そんなことしたらダメ!!!はい、アプリケーションはデータを送信する前にチェックを行う必要がありますが、データの整合性とビジネスロジックはデータベースレベルである必要があります。整合性はデータベースの鍵であり、データベースレベルで実施する必要があります。
@Meff:関数を使用するアプローチには潜在的な問題があります。簡単に言えば、SQL ServerのCHECK制約は単一行を作業単位として設計されており、結果セットで作業するときに欠陥があります。詳細については、次を参照してください:[ http://blogs.conchango.com/davidportas/archive/2007/02/19/Trouble-with-CHECK-Constraints.aspx] [1] 。
[1]:David Portasのブログ:CHECK制約の問題。
Skliwzと同じ。 トリガーの標準的な使用を知らせるために、監査テーブルがあります。監査したいテーブル(誰が何をいつ変更したか)を更新/挿入/削除する多くのプロシージャがある場合、最も簡単な方法はトリガーです。 1つの方法は、単にテーブルにフラグを追加して(何らかのunicity制約でアクティブ/非アクティブ)、監査テーブルに何かを挿入することです。
テーブルに履歴データを保持しないようにする別の方法は、監査テーブルの前の行をコピーすることです...
多くの人々がそれを行う多くの方法を持っています。ただし、1つ確実なことは、このテーブルの更新/挿入/削除ごとに挿入を実行する必要があることです
さまざまな場所に挿入物を書き込まないようにするには、ここでトリガーを使用できます。
私はここで制約について全員に同意します。できるだけ使用してください。
特に新しい開発者では、トリガーを使いすぎる傾向があります。トリガーが別のトリガーを起動し、それが最初のトリガーを繰り返す別のトリガーを起動し、サーバーを拘束するカスケードトリガーを作成する状況を見てきました。これはトリガーの最適ではないユーザーです; o)
とはいえ、トリガーには場所があり、適切なときに使用する必要があります。これらは、データの変化を追跡するのに特に適しています(Mark Brackettが述べたように)。 「私のビジネスロジックを配置するのに最も意味があるのはどこですか」という質問に答える必要がありますか?ほとんどの場合、それはコードに属していると思いますが、心を開かなければなりません。