web-dev-qa-db-ja.com

コードでのDBクエリまたはストアドプロシージャの使用

私の同僚の何人かは、データベースでストアドプロシージャを使用すると、データベースの多くのビジネスロジックに追加されるため、データをロジックから分離しておく必要があると言っています。他の同僚は、ソースコードに文字列としてDBクエリを追加することは変更が難しいだけでなく、セキュリティリスクももたらすと私に言っています。

ゲッターやセッターなどの単純なタスクにのみ使用し、データベース内のビジネスロジックを回避する限り、ストアドプロシージャをデータベースに配置することに傾倒しています。

Entity Frameworkなどを使用して、データベースとロジックの間にORMレイヤーを追加することで、両方の問題を解決できる可能性があることを知っています。ただし、このシナリオでどちらの方法が最適かはまだわかりません。

3
Benny Skogberg

ここで考慮すべき点がいくつかあります。問題の領域を理解するのに役立つように、十分に詳しく説明します。個人的には、RDMSについては、ストアドプロシージャを使用することを好みます。その理由についてはすぐに説明します。


個別のアプリケーションレイヤーでは、ダーティデータがレイヤーに入り、破損を引き起こすのを防ぐために、そのレイヤーの境界に十分なコントロールが配置されていることを確認する必要があります。これは、レイヤーが公開されているAPI、内部API(たとえば、サービスとネゴシエートするフロントコントローラー)、または外部レイヤーへの呼び出し(たとえば、データストアとの通信)であるかどうかに関係なく当てはまります。 DDDではこれは汚職防止レイヤーと呼ばれ、OOPではいくつかの名前(Design By Contract、Assertions、Pre-/Post-Conditions))で呼ばれ、単純な厳密に型指定された入力変数と出力変数として形成されます。いずれの場合も、このレイヤーの目的は、レイヤーが入力操作と出力操作の通信標準を一貫して予測どおりに実施できるようにすることです。

ストアドプロシージャとアドホックSQLとの関係は何ですか?

データベースに対してアドホックSQLを実行できるようにすることは cowboycoding の形式であり、SQLクエリ自体は管理されず、その有効性の唯一の尺度は、SQLクエリが正常に実行されたかどうかであり、適切なセーフティネットのみが、開発者やコードレビューアによる(アプリケーションの)知恵です。これを、ビジネスロジックをデータベースに入れてはならない(つまり、データ構造が損なわれないようにするための制約やトリガーがない)という潜在的な概念と組み合わせると、データの整合性にリスクが生じ始めます。この例は、データベースに保存されているオブジェクトであり、複数のテーブルで更新または挿入する必要があります。1つまたは2つのinsertステートメントを見逃した場合、無効なデータ、意味のないデータ、または孤立したデータになる可能性があります。ストアドプロシージャを使用した場合、そのタイプのすべての操作が、関連する行を挿入/更新allする要件に準拠していることを確認できます。

ビジネスロジックがデータベースに属していないという概念で私が選択しなければならない骨は2つあります。

  1. データベースは、それをデータストアとして利用するアプリケーションと緊密に結合されています。データベースとアプリケーションを分離可能であると見なすことはできません。一方がなければ、一方が意味を持って存在しない可能性があります。
  2. ビジネスロジックは、ビジネスルールとデータロジックという2つの主要なアイデアで構成されています。ビジネスルールはアプリケーションに属し、データロジックはデータストアに属します。

私の最初のポイントはかなり明白であり、それ以上の説明は必要ありません。 2つ目のポイントは、拡張が必要ですが...

NOSQLとDDDの登場により、現代のデータとデータの使用はますます複雑になり、多くの場合、データは独自の内部構造と管理ルールを持つリッチエンティティの観点から考えられています。リッチオブジェクトを有効にするルールは、ビジネスルールです。データの保存方法は、データロジックです。データロジック、またはオブジェクトがストレージで一緒にハングする方法は、そのフォームがビジネスルールのコンテキストで適切であるかどうかとはまったく異なります。データアーキテクトは、特定のオブジェクトを複数のテーブルにまたがる行のセットとして、またはJSON文字列として1つの行としてデータベースに格納する必要があると考える場合があります。どちらの方法でも、オブジェクトはビジネスルールのコンテキストで有効なままです。データストレージの問題は通常、ビジネスルールの問題とは異なり、次のようなことを中心に展開します。

  • CRUD操作はどのくらい高速で、ロックや遅延のリスクがありますか?
  • データに対するSELECT操作はどの程度効率的ですか?
  • 必要なインデックス、統計テーブル、およびその他の最適化の数、およびそれらが書き込み操作に与える影響は何ですか?
  • データは一意に識別できますか?
  • 利用可能なデータ型を考慮して、データは効率的に保存されていますか?

これらの質問に対する回答は、アプリケーションの機能強化に応じて、異なる速度または異なるタイミングで変更される場合があります。データロジックをビジネスルールから分離することにより、データ管理者は目的に最適なデータスキーマと機能を選択できます。ストアドプロシージャを介してのみデータのやり取り(取得と設定の両方)を公開することにより、データ管理者が基になるデータ構造を自由に変更できるようにしながら、親アプリケーションの一貫したインターフェイスを維持できます。

ただし、イデオロギー設計の決定をサポートするためにビジネス(IT部門を参照)がどの程度の能力を備えているかを考慮する必要があります。あなたが小さな会社で、一人がフロントエンド、バックエンド、そしてデータベースの仕事をしているケースかもしれません。大規模な組織で、各アプリケーション層にチームが割り当てられている場合があります。コードに取り組んでいる人が少ないほど、知識が広くなります(qv Information Silo )。これは、開発者がプロ​​セスに関するすべてを知っており、含めることを無視するため、レイヤー間のアサーションが不足する可能性があります論理的アサーション。ただし、(大小にかかわらず)コードに実装する間接性とアサーションが多いほど、記述と維持に時間がかかります。理論と実践、理想主義、実用主義を比較検討する必要があります。これに加えて、アプリケーションの寿命が限られているかどうか、スタッフのスキルセット、それらの管理方法、SDLCがどの程度厳しく管理されているか、さらにはすべての人の性格とコーディングの習慣を考慮する必要があります。これは、テクニカルリードと上級管理職の恐ろしくて恐ろしい世界です。


考えながら、ビジネスルールがデータベースに有効に適合し、そこに正しく配置できる場所を示す例を次に示します。これは大げさなことではありませんが、「ビジネスロジックはデータベースに属していない」などの格言には例外があり、彼らのアイデアがどんなに高貴であっても、次のことを示します。

ユーザーの詳細が保存され、それらの詳細への変更が監査ログテーブルに保存されるクライアント管理システムがあるとします。モデレーターがクライアントにこのFYの税詳細を提供していないとしてフラグを立てることができるアプリケーションの新機能が必要です。これは、すべてのトランザクションに最高レートで課税する効果があります。開発者はこの新しい機能をコード化しますが、監査テーブルへの挿入を含めることを怠ります。彼らはそれをピアレビューのためにシニアに渡し、何らかの理由でピアレビューを通過して本番環境に入ります。数か月後、クライアントは最大課税率を誤って請求されていると不平を言っています。問題の根本的な原因は開発者です-しかし、更新を誤って実行したビジネスユーザーがいました。これは、知識またはトレーニングのギャップを示しています。どのユーザーがいつ更新を実行したかを示すレコードが監査ログテーブルにないため、これに対処することはできません。根本的なコードの問題は解決できますが、運用上の問題にいつ対処できるか、いつ対処できるかは、時が経てばわかります。

この問題は、「監査目的でデータへのすべての変更を記録する必要がある」という会社の方針を考慮せずに、データベースに対して独自のCRUD操作を実行したアドホックSQLの結果でした。 UPDATE列を1に設定するinvalildTaxFileDetailsステートメントは、BITデータ型のコンテキストで本質的に有効であるため、データベースは文句を言いませんでした。しかし、データは完全性を失っており、会社の財務的リスクや評判リスクにつながる可能性があります。場合によっては、これがまったく気付かれないこともあり、顧客は契約期間全体にわたって過大請求され、競争力のあるコストのために、払い戻しを受ける権利さえないことに気づかずに別の場所にビジネスを移す可能性があります。

9
e_i_pi

重要なことは、生のSQLとビジネスロジックの間に抽象化レイヤーを設けることです。

昔は、これはストアドプロシージャでした。すべてのアプリは、ランダムSQLを実行するのではなく、dbに直接接続してsprocを呼び出します。

データベースが変更されたら、sprocを更新すると、アプリは機能し続けます。

実行する新しいSQLがある場合、sprocプロセスを作成すると、既存のsprocの再利用とデータベースのパフォーマンスを確実に考慮することができます。

ただし、最近の抽象化レイヤーは、リポジトリクラスまたはリポジトリをラップするAPIである可能性が高くなっています。

これにより、同じ分離の利点が得られ、より強力な機能とデータベースボックスから実行されるコードのスケーラビリティにアクセスできます。

ここで、SQLとコードを維持することで開発が容易になり、単一のデータベースに複数のAPIバージョンをデプロイできるようになります。

Sprocを変更する方が「簡単」であることに基づく議論は誤りです。人々が意味することは、コードベースの場合と同じ変更コントロールをデータベースに適用していないということです。

私はsprocを「変更する」ことができないはずです。ソース管理、移行スクリプト、ステージングサーバー、単体テストなどのスキーマが必要です

結局のところ、コード化されたパラメーター化されたSQLを使用します。その速度と同じくらい速く、私がより問題を感じるデータベースの変更を最小限に抑えます。

データベースエンジニアはしばしば、ますます複雑なsprocを作成するように誘惑され、それがdbのデバッグとスローダウンの悪夢になります。これはsprocに固有のものではなく、単に「ハンマーを持っていると、すべてが釘のように見える」問題です。

5
Ewan

参照 データベース:アプリケーションロジックはどこで実行する必要がありますか?

これは、関係するデータの量と要求がどれだけ複雑かによって異なります。セキュリティとプライバシーは他の側面です。同様に、欧州一般データ保護規則(GDPR)のような適用法を考えてください。データベースが準拠していて、一部のアプリケーションが準拠していない場合は、後者も準拠させる必要があります。これがストアドプロシージャの正当な理由です。

1
Klaas-Z4us-V