13

複数の (ネストされた) サブクエリを含むやや複雑なクエリがあり、アプリケーション開発者が利用できるようにしたいと考えています。クエリは汎用的であり、データ セットのコレクションに対して計算された値を使用してビューを生成します。開発者は、クエリが返すものから一部のレコードのみを必要とすることが期待されます (つまり、一部のエンティティの ID または日付範囲または一部の結果を制限します)。そのような)。

これを実装するには、次の 3 つの方法があります。

  1. 開発者が各アプリケーションにクエリを埋め込み、必要に応じて独自のWHERE句を追加できるようにします。
  2. 開発者が必要とするすべての条件をパラメーターとして受け入れるストアド プロシージャを作成します (議論のために、予見可能な将来に何が必要になるかを予測できるとしましょう)。プロシージャは複雑なクエリを実行し、それをフィルター処理します。渡されたパラメータに従って。
  3. いくつかのサブビューを持つビューとしてクエリを実装し (MySQL はビューでサブクエリを許可しないため)、開発者にこれをテーブルとして使用WHEREさせ、各アプリケーションに必要なフィルターを適用させるために使用します。現在、いくつかのサブクエリが複数回使用され、サブビューとしてそれらを実行すると重複が防止されるため、3 つの追加のサブビューを検討しています。

より良いパフォーマンスは何ですか?(すべてのインデックス作成がすべてのケースで同等であると仮定します)可能であれば、最悪のシナリオに進みます。

コードのメンテナンスに関しては何が良いと思いますか?

4

2 に答える 2

7

私は「良い」を定義する質問が好きです-あなたは特にパフォーマンスと保守性について尋ねました。それは答えがそのトレードオフについて話すことを可能にします。

パフォーマンスの観点からは、クエリとデータが予想されるシナリオに適合する限り、3つのオプションの間に違いはないと思います。100倍のデータでテストし、「where」句を広げて何が起こるかを確認しますが、インデックス構造などは、ストアドプロシージャから同じSQLを実行するかどうかよりも、パフォーマンスに影響を与える可能性が高くなります。ビュー、またはクライアントアプリケーションから。

その質問に答える最良の方法はそれをテストすることです-もちろん、オーバーフロー者が与えることができる一般的な「x、y、またはzを期待する」答えを無効にする可能性のある多くの特定の詳細があります。パフォーマンスが重大な懸念事項である場合は、データベース入力ツール(Redgateが作成、過去にDBMonsterを使用したことがあります)を使用して、3つのオプションすべてを試してください。

メンテナンスの観点から、私はオプション4を提供します。これは、私の見解では、群を抜いて最高です。

オプション4:データへのアクセスをカプセル化するデータアクセスライブラリを構築します。ライブラリにメソッドとパラメーターを公開させて、レコードの選択を改善します。仕様パターン(http://en.wikipedia.org/wiki/Specification_pattern)の使用を検討してください。ライブラリ内で最適なクエリを使用し、実装の詳細について開発者を煩わせないでください。

それが機能しない場合(異種のアプリケーションコード、単純な要件にはあまりにも多くの変更)、次のようにオプションを評価します。

  1. 埋め込みSQL:このSQLが再利用される回数によっては、これで問題ない場合があります。SQLを実行するコードの部分が1つしかない場合、それはデータアクセスライブラリと論理的に似ています。ただし、同じスニペットを多くの場所で再利用する必要がある場合は、バグの原因である可能性があります。SQLの小さな変更を複数の場所で繰り返す必要があります。

  2. ストアドプロシージャ:私は通常、メンテナンス上の理由からストアドプロシージャが嫌いです。これらは、過負荷によってもろくなり、手順的な考え方を生み出す傾向があります。たとえば、このSQL計算を別のストアドプロシージャで使用するための他の要件がある場合、非常に迅速に、ストアドプロシージャが相互に呼び出す手続き型プログラミングモデルになります。

  3. ビュー:これはおそらく最良の選択です。特定のデータロジックを1つの場所に配置しますが、アクセスルートは手続き型ステートメントを実行するのではなく、SELECTステートメントを経由するため、セットベースのロジックの使用を促進します。ビューは他のクエリに簡単に組み込むことができます。

于 2011-10-24T11:56:44.310 に答える
3

適切に実装されていれば、3 つのソリューションのいずれも保守には問題ありませんが、移行プロセス (コードまたはデータベースの移行) でそれぞれをどのように扱うかを念頭に置いてください。

クエリが大きい場合、ストアド プロシージャはより小さなサイズのクエリを送信するため、帯域幅のオーバーヘッドが少なくなるため、パフォーマンスが少し向上します。このソリューションを使用すると、セキュリティが少し強化される場合もあります。

保守ソリューションについては、データベースを変更せずにクエリを変更できるため、1番目と2番目のソリューションをお勧めします。最初の解決策を選択した場合は、クエリ呼び出しを関数内にラップして、変更を加える場所が 1 つだけになるようにします。

開発者の観点から、私はビュー ソリューションを選択します。なぜなら、ビュー ソリューションが最も透過的なものだからです。つまり、通常のテーブルだけをクエリするようなもので、describe コマンドでテーブル構造を確認したり、必要なフィールドや条件を選択したりできます。クエリ、または別のテーブルとの結合など...

where句の柔軟性については、提案されたソリューションのいずれかで実現できます。ラッピング関数に where パラメーターを追加することも (1)、where パラメーターをストアド プロシージャに追加することもできますが、インジェクションには注意することもできます (2)、または開発者がビューで通常どおり where 句を追加することもできます (3)。

MySQL ではビューは一時テーブルではないことに注意してください。クエリが非常に複雑な場合、クエリがさまざまな方法で頻繁に使用される場合 (キャッシュ パフォーマンスの向上を無効にする)、このソリューションは最適ではありません。プログラムされたタスク/ cron(たとえば、1日、1週間、必要に応じて)で期間ごとに更新するか、propperトリガーを設定して更新する一時テーブルソリューション(カウンターテーブル)を検討します。このソリューションにより、パフォーマンスが大幅に向上する可能性があります。

これが役に立てば幸いです。ビュー ソリューションが一番気に入っていますが、データベースの観点から開発するのはもっと複雑かもしれません。

于 2011-10-24T09:48:47.863 に答える