16

私はこれとしばらく戦っています。フィルタリングに使用される3つのパラメーターを受け取るストアドプロシージャがあります。特定の値が渡された場合、それをフィルタリングしたいと思います。-1が渡されたら、全部ください。

私はそれを次の2つの方法で試しました:

最初の方法:

SELECT field1, field2...etc  
FROM my_view  
WHERE  
parm1 = CASE WHEN @PARM1= -1 THEN parm1  ELSE @PARM1 END  
AND parm2 = CASE WHEN @PARM2 = -1 THEN parm2  ELSE @PARM2 END  
AND parm3 = CASE WHEN @PARM3 = -1 THEN parm3  ELSE @PARM3 END

2番目の方法:

SELECT field1, field2...etc  
FROM my_view  
WHERE  
(@PARM1 = -1 OR parm1 = @PARM1)  
AND (@PARM2 = -1 OR parm2 = @PARM2)  
AND (@PARM3 = -1 OR parm3 = @PARM3)  

私はどこかで、2番目の方法が短絡し、trueの場合は2番目の部分を評価しないことを読みました。私のDBAは、テーブルスキャンを強制すると言いました。私はこれを確認していませんが、場合によっては実行が遅くなるようです。

このビューが選択するメインテーブルには約150万のレコードがあり、ビューは他の約15のテーブルに結合して、他の多くの情報を収集します。

これらの方法はどちらも遅いです...私を瞬時から2〜40秒のどこかに連れて行ってくれますが、これは私の状況ではまったく受け入れられません。

それを特定の対-1のそれぞれの別々のケースに分解することを含まないより良い方法はありますか?

どんな助けでも大歓迎です。ありがとう。

4

5 に答える 5

6

私はどこかで、2番目の方法が短絡し、trueの場合は2番目の部分を評価しないことを読みました。私のDBAは、テーブルスキャンを強制すると言いました。

あなたは間違って読んだ。短絡しません。あなたのDBAは正しいです。クエリオプティマイザではうまく機能せず、テーブルスキャンを強制する可能性があります。

最初のオプションは、それが得るのとほぼ同じくらい良いです。物事を改善するためのオプションは、動的SQLまたはフィルター列のすべての可能な組み合わせを使用した長いストアドプロシージャであるため、独立したクエリプランを取得できます。「WITHRECOMPILE」オプションを使用することもできますが、役に立たないと思います。

于 2009-10-08T19:15:06.613 に答える
5

SQL Server 2005 以降を実行している場合は、IF を使用して、適切な WHERE を使用して複数のバージョンのクエリを作成し、インデックスを使用できます。各クエリ プランは、クエリ キャッシュに配置されます。

また、このトピックに関する非常に包括的な記事は次のとおりです。

Erland Sommarskog による T-SQL の動的検索条件

複数のオプションの検索条件を使用してクエリを作成しようとするすべての問題と方法をカバーしています

目次は次のとおりです。

  序章
      ケーススタディ: 注文の検索
      ノースゲイル データベース
   動的 SQL
      序章
      sp_executesql の使用
      CLR の使用
      EXEC() の使用
      キャッシングが本当に必要なものではない場合
   静的 SQL
      序章
      x = @x または @x が NULL です
      IF ステートメントの使用
      ウマチャンダーのトリックの袋
      一時テーブルの使用
      x = @x AND @x は NULL ではありません
      複雑な条件の処理
   ハイブリッド ソリューション – 静的 SQL と動的 SQL の両方を使用
      ビューの使用
      インライン テーブル関数の使用
   結論
   フィードバックと謝辞
   改訂履歴
于 2009-10-08T19:19:56.683 に答える
2

すべてが必要なときに null 値を渡す場合は、where 句を次のように記述できます。

   Where colName = IsNull(@Paramater, ColName)  

これは基本的に最初の方法と同じです...列自体がnull可能でない限り機能します...列のnull値それをわずかに台無しにします。

高速化する唯一の方法は、Where 句でフィルター処理されている列にインデックスを追加することです。すでにありますか?そうでない場合は、劇的な改善がもたらされます。

于 2009-10-08T19:17:11.680 に答える
0

それから私が考えることができる他の方法はありません:

どこ

(MyCase IS NULL OR MyCase = @MyCaseParameter)AND...。

2つ目は、私に言わせれば、開発者にとってよりシンプルで読みやすいものです。

于 2009-10-08T19:13:59.317 に答える
0

SQL 2008 以降では、次のような最適化が改善されています。(MyCase IS NULL OR MyCase = @MyCaseParameter) AND ....

アップグレードでき、OPTION (RECOMPILE)可能なすべてのパラメーターの組み合わせに対して適切なパフォーマンスを得るために を追加すると (これは、すべての可能なパラメーターの組み合わせに適した単一のプランがない状況です)、これがうまく機能することがわかります。

http://blogs.msdn.com/b/bartd/archive/2009/05/03/sometimes-the-simplest-solution-isn-t-the-best-solution-the-all-in-one-search-クエリ.aspx

于 2011-03-03T17:09:23.640 に答える