アプリケーションでロジックを直接記述するのではなく、いつストアドプロシージャを使用する必要がありますか?ストアドプロシージャのメリットを享受したいのですが、アプリケーションロジックをデータベースとアプリケーションに分散させたくないのです。
これに関して考えられる経験則はありますか?
うわー...ここで流れに逆らって直接泳ぎ、「ほとんどいつも」と言います。理由の洗濯物のリストがあります-いくつか/多くは他の人が主張すると確信しています。しかし、データアクセス層としてストアドプロシージャを使用する場合と使用しない場合の両方でアプリを開発しました。適切に記述されたストアドプロシージャを使用すると、アプリケーションの記述が非常に簡単になります。次に、十分に文書化されたパフォーマンスとセキュリティの利点があります。
これは完全にあなたの環境に依存します。質問への答えは、実際にはコーディングの問題ではなく、分析の問題でもありませんが、ビジネス上の決定です。
データベースが1つのアプリケーションのみをサポートし、データベースと適度に緊密に統合されている場合は、柔軟性の理由から、ロジックをアプリケーションプログラム内に配置することをお勧めします。このような状況では、共通の機能を使用してデータベースを単純なデータリポジトリとして扱うだけで、ベンダー、実装、展開などの柔軟性がほとんど失われず、「データベースはデータ用である」という純粋な議論の多くが実証的になります。本当。
一方、企業データベースを処理している場合は、通常、複数のアクセスパスを使用することで識別できますが、可能な限りセキュリティを強化することを強くお勧めします。少なくともすべての適切な制約を有効にする必要があり、可能であれば、データへのアクセスはビューと手順のみを介して行う必要があります。これらの場合、泣き言を言うプログラマーは無視されるべきです...
SPの使用の有無をめぐって宗教戦争に飛び込むコーダーは、通常、どちらか一方の環境でしか働いていないため、限られた経験を鋳鉄の位置に外挿します。来ますが、全体像を見逃しています。いつものように、どのタイプのコーディング方法を好むかではなく、ビジネス/顧客/ユーザーのニーズに基づいて決定する必要があります。
コメントで言いましたが、ここでもう一度言います。
セキュリティ、セキュリティ、セキュリティ。
SQLコードがアプリケーションに埋め込まれている場合は、基になるテーブルを直接アクセスできるように公開する必要があります。このは最初は大丈夫に聞こえるかもしれません。データベース内のすべてのvarcharフィールドをスクランブルするSQLインジェクションに見舞われるまで。
一部の人々は、魔法の引用符または埋め込みSQLを適切にエスケープする他の方法を使用してこれを回避すると言うかもしれません。ただし、問題は、開発者が正しくエスケープしなかった1つのクエリです。または、コードのアップロードを許可しなかった開発者。または、攻撃者がコードをアップロードできるようにクラックされたWebサーバー。または...あなたはポイントを取得します。すべての拠点をカバーするのは難しいです。
私のポイントは、すべての最新のデータベースにはセキュリティが組み込まれているということです。テーブルへの直接アクセス(選択、挿入、更新、削除)を拒否し、すべてにs'procを強制的に実行させることができます。そうすることで、一般的な攻撃は機能しなくなります。代わりに、攻撃者は時間をかけてシステムの詳細を知る必要があります。これにより、費やす時間の点で「コスト」が増加し、ドライブバイやワーム攻撃が停止します。
すべてに対して自分自身を保護することはできないことはわかっていますが、時間をかけてアプリを設計し、それをクラックするコストがメリットをはるかに上回るようにすると、データ損失の可能性を大幅に減らすことができます。つまり、利用可能なすべてのセキュリティツールを利用することを意味します。
最後に、別のrdbmsに移植する必要があるため、s'procを使用しないという考えについては、次のようになります。まず、ほとんどのアプリはデータベースサーバーを変更しません。次に、それが現実的な可能性がある場合は、とにかくANSIsqlを使用してコーディングする必要があります。あなたはあなたのprocsでそれを行うことができます。第三に、何があってもすべてのSQLコードを再評価する必要があり、そのコードが1か所にあるとはるかに簡単になります。第4に、最新のデータベースはすべてs'procsをサポートするようになりました。第5に、s'procを使用する場合、実行中のデータベースに合わせてSQLをカスタム調整して、その特定のデータベースのSQL拡張機能を利用できます。
私にとって複雑なデータベースクエリは、ストアドプロシージャとして終わる傾向があります。考慮すべきもう1つの考えは、データベースがアプリケーションとは完全に分離されている可能性があるということです。 Oracle DBを実行していて、基本的に組織内の他のアプリケーション開発者が呼び出すAPIを構築しているとします。それらから複雑なものを隠し、その場所にストアドプロシージャを提供することができます。
非常に簡単な例:
registerUser(username, password)
いくつかの異なるクエリを実行することになり(存在するかどうかを確認し、設定テーブルにエントリを作成するなど)、それらをカプセル化することをお勧めします。
もちろん、人によって視点も異なります(DBAとプログラマー)。
私はストアドプロシージャを避ける傾向があります。デバッグツールはより原始的である傾向があります。エラー報告は(サーバーのログファイルと比較して)難しい場合があり、少なくとも私には、実際の利益を得るために別の言語を追加しているように見えます。
特にサーバー上で大量のデータを処理する場合や、もちろんコードでは実行できないデータベーストリガーの場合に、これが役立つ場合があります。
それ以外は、コードですべてを実行し、データベースをコードを実行するものではなく、データの大きなダンプとして扱う傾向があります。
考えてみてください とにかく、誰がストアドプロシージャを必要としますか? :
最新のデータベースと実際の使用シナリオの場合、ストアドプロシージャアーキテクチャには重大な欠点があり、実用的なメリットはほとんどないと思います。 ストアドプロシージャはデータベースアセンブリ言語と見なす必要があります:最もパフォーマンスが重要な状況でのみ使用します。
および ストアドプロシージャを使用しない理由 :
あなたができる絶対的な最悪のこと、そしてそれはマイクロソフトの開発の世界で恐ろしく一般的です、 sprocと中間層コードの間で関連する機能を分割する 。 Grrrrrrrr。コードを脆弱にするだけで、システムを理解するための知的オーバーヘッドが増加します。
基本的に、データベースから取得する必要のないデータを含む操作を実行する必要がある場合。たとえば、あるテーブルを別のテーブルのデータで更新したい場合、データベースへの1回のショットですべてを実行できるのであれば、データを取り出してから戻すことはほとんど意味がありません。
ストアドプロシージャの使用が許容されるもう1つの状況は、アプリケーションを別のデータベースベンダーにデプロイしないことが100%確実な場合です。 Oracleショップで、同じデータベースと通信するアプリケーションが多数ある場合は、すべてのアプリケーションが一貫した方法でデータベースと通信するようにストアドプロシージャを用意するのが理にかなっています。
3つのシナリオのうちの1つでストアドプロシージャを使用しました。
速度速度が最も重要な場合、ストアドプロシージャは優れた方法を提供します
複雑さ複数のテーブルを更新していて、コードロジックが将来変更される可能性がある場合は、ストアドプロシージャを更新して、再コンパイルを回避できます。ストアドプロシージャは、1回のストロークで大量のデータを更新するための優れたブラックボックス方式です。
トランザクション複数のテーブルにまたがる挿入、削除、または更新を行っているとき。すべてをトランザクションでラップします。エラーが発生した場合、トランザクションをロールバックしてエラーをスローし、データの破損を回避するのは非常に簡単です。
下の2つは、コードで非常に実行可能です。ただし、ストアドプロシージャは、複雑でトランザクションレベルの操作が重要な場合にブラックボックスで機能する方法を提供します。それ以外の場合は、コードレベルのデータベース操作に固執します。
以前はセキュリティが理由の1つでした。ただし、LINQやその他のORMを使用すると、コードレベルのDAL操作は以前よりもはるかに安全になります。ストアドプロシージャは安全ですが、LINQのようなORMも安全です。
すべてのコードがストアドプロシージャにある場合、必要に応じてデータベースをリファクタリングする方がはるかに簡単です。ロジックの変更もプッシュするのがはるかに簡単です。また、パフォーマンスチューニングははるかに簡単であり、遅かれ早かれ、ほとんどのデータベースアプリケーションでパフォーマンスチューニングが必要になります。
また、カプセル化の問題として、またDRYの哲学においても非常に役立ちます。たとえば、コード内のいくつかのクエリに必要なテーブル内の計算に保存された関数を使用します。このようにして、より良いパフォーマンスを使用し、計算が常に同じ方法で行われるようにします。
アーキテクチャのビジネスロジック層にあるべき高度な機能やロジックには使用しませんが、モデル層に焦点を当てます。モデル層では、機能がデータベース設計に明確に焦点を当てており、データベース設計を壊すことなく変更できる柔軟性があります。他のレイヤーへのAPI。
すべてのレポートニーズにストアドプロシージャを使用します。彼らは通常、データをより速く取得でき、レポートが何らかの計算などを行う代わりに直接吐き出すことができる方法でデータを取得できます。
また、コードベース内にあると読みにくい複雑または複雑なクエリにストアドプロシージャを使用します。
私は常にストアドプロシージャを使用する傾向があります。個人的には、すべてのメンテナンスが簡単になると思います。次に、セキュリティとパフォーマンスに関する考慮事項があります。
クリーンで、適切にレイアウトされ、十分に文書化されたストアドプロシージャを作成するようにしてください。
速度とセキュリティの考慮事項に加えて、メンテナンスと変更を容易にするために、可能な限りストアドプロシージャに固執する傾向があります。アプリケーションにロジックを配置し、後でSQLロジックにエラーがあるか、何らかの方法で異なる動作をする必要があることがわかった場合、多くの場合、アプリ全体を再コンパイルして再デプロイする必要があります(特に、WPFなどのクライアント側アプリの場合) 、Win-Formsなど)。ストアドプロシージャにロジックを保持している場合は、プロシージャを更新するだけで、アプリケーションに触れる必要はありません。
メリットが得られる可能性のある特定のシナリオには、「(n + 1)」スケーラビリティの問題に関する状況が含まれます。あらゆる種類の多次元/階層的状況がこのシナリオに関係する可能性があります。
別のシナリオには、テーブルを処理するときに何らかのプロトコルを実行するユースケースが含まれます(ヒント:トランザクションが関与する可能性のある定義済みのステップ)。これは、参照の局所性から恩恵を受ける可能性があります。サーバー内にいるため、クエリが恩恵を受ける可能性があります。 OTOH、ステートメントのバッチをサーバーに直接提供できます。特に、XA環境を使用していて、連合データベースにアクセスする必要がある場合。
「一般的にsprocを使用する必要がある」ではなく、ビジネスロジックについて話している場合、大規模なセットベースの操作を実行するとき、またはロジックを実行するときに多数の呼び出しが必要になるときは、ビジネスロジックをsprocに配置する必要があります。アプリからデータベースに。
私はこれでいくつかの非常に悪い経験をしました。
私は代わりにストアドプロシージャに反対していませんが、ストアドプロシージャを不必要に使用すると非常にコストがかかる可能性があります。
まず、ストアドプロシージャがデータベースサーバーで実行されます。つまり、50台のWebサーバーと1台のデータベースサーバーを備えたマルチサーバー環境では、50台の安価なマシンにワークロードを分散する代わりに、1台の高価なマシンをロードします(データベースサーバーは通常、重量のあるサーバーとして構築されるため)。そして、単一障害点を作成するリスクがあります。
第二に、ストアドプロシージャだけでアプリケーションを作成するのは簡単ではありませんが、超人的な努力をしたアプリケーションに出くわしました。そのため、保守に費用がかかることになります。これは2つの異なるプログラミング言語で実装されており、ストアドプロシージャはソースアーカイブではなくDBMSに確実に格納されるため、ソースコードもすべて1か所にあるとは限りません。誰かが管理/悩まされたことがあると仮定して、データベースサーバーからそれらを引き出し、ソースアーカイブします。
したがって、かなり厄介なアプリアーキテクチャとは別に、複数のスキルが必要になるため、それを維持できる資格のあるチンパンジーのセットも制限します。
一方、ストアドプロシージャは、次の場合に非常に役立ちます。
複数のシステム間で、ある種のデータ整合性を維持する必要があります。つまり、保存されたロジックは単一のアプリに属していませんが、参加しているすべてのアプリからの一貫した動作が必要です。これのある程度の量は、外部キーとトリガーの形で現代のアプリではほとんど避けられませんが、場合によっては、主要な編集と検証も必要になることがあります。
クライアントとしてではなく、データベースサーバー自体でロジックを実行することによってのみ達成できるパフォーマンスが必要です。しかし、私が言ったように、それを行うと、DBMSサーバーのシステムリソース全体に食い込んでしまいます。したがって、クライアントにオフロードできる問題のある操作の重要な部分がある場合は、それらを分離して、DBMSサーバーに最も重要なものを残すことができるようにする必要があります。
私はそれらが頻繁にそしてよく使われるべきであることに同意します。
私が考えるユースケースは、非常に説得力があり、非常に役立つと思います。いくつかのテーブルに分割する必要がある多くの生の情報を取り込む場合です。一部のデータには、既存のレコードが含まれている可能性があり、外部で接続する必要があります。キーIDの場合、存在する場合はチェックして挿入するか、そうでない場合はキーを返すことができます。これにより、すべてがより均一で簡潔になり、長期的に保守しやすくなります。
私が提案する唯一のケースに対してそれらを使用するのは、アプリサーバーで最もよく行われるクエリ間で多くのロジックまたは数値計算を行っている場合ですOR ifあなたは、コード内のロジックのallを維持することが、保守性/何が起こっているのかを理解するために重要である会社で働いています。誰もが必要とし、簡単に理解できるすべてのものでいっぱいのgitリポジトリがある場合、非常に価値があります。
それはあなたの聴衆にも依存します。インストールのしやすさとDBMS間の移植性はあなたにとって重要ですか?
プログラムを簡単にインストールでき、さまざまなデータベースシステムで簡単に実行できるようにする必要がある場合は、ストアドプロシージャを避け、コード内の移植性のないSQLにも注意する必要があります。
ストアドプロシージャは、操作を収集する方法ですデータベース側で一緒に実行する必要があります、それでもデータベース側でそれらを保持する。
これも:
等.
ストアドプロシージャの主な問題は、保守が難しいことです。
したがって、ストアドプロシージャを作成する必要があります他のすべてのコードと同じくらい簡単に保守できます。
私のブログにこれに関する記事があります: