1

非常に大きなテーブルがあります (1,500 万行、これは監査テーブルです)。

特定の日付以降で、特定の基準を満たす監査テーブル内のオカレンスをチェックするクエリを実行する必要があります (当日のみに行われた監査レコードを探しています)。

私が実行すると:

SELECT Field1, Field2 FROM AUDIT_TABLE WHERE AUDIT_DATE >= '8/9/12'

結果はかなり速く返されます (数秒、1,500 万行では悪くありません)

私が実行すると:

SELECT Field1, Field2 FROM AUDIT_TABLE WHERE AUDIT_DATE >= @DateTime

11 ~ 15 秒かかり、テーブル全体のスキャンが実行されます。

私が照会している実際のフィールドは DATETIME 型であり、インデックスもそのフィールドにあります。

4

1 に答える 1

7

おそらく、ある時点で、テーブル スキャンがそのパラメータ値に対して最も効率的な方法であるテーブルを十分に選択するパラメータを誰かが使用したためです。この方法でクエリを 1 回実行してみてください。

SELECT ... FROM AUDIT_TABLE WHERE AUDIT_DATE >= @DateTIme OPTION (RECOMPILE);

次に、コードを次のように変更します。

SELECT ... FROM dbo.AUDIT_TABLE WHERE AUDIT_DATE >= @DateTime;

プレフィックスを使用するdbo.と、少なくとも、異なるスキーマを持つ異なるユーザーが異なるバージョンのプランでプラン キャッシュを汚染するのを防ぐことができます。また、保存されている悪い計画から将来のクエリの関連付けを解除します。

最近の行の選択 (% が小さい) と多数の行の選択を変更する場合は、おそらくそこに OPTION (RECOMPILE) を残します。毎回再コンパイルでマイナーな CPU ペナルティを支払うことは、ほとんどのクエリで不適切なプランに行き詰まるよりも安く済みます。

私が見た別のトリックは、パラメーター スニッフィングをバイパスするために使用されます。

ALTER PROCEDURE dbo.whatever
  @DateTime DATETIME
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @dt DATETIME;
  SET @dt = @DateTime;

  SELECT ... WHERE AUDIT_DATE >= @dt;
END
GO

これは一種の汚い、直感的でないトリックですが、オプティマイザーがパラメーター値をよりよく把握し、その値を最適化する可能性が高くなります。

于 2012-08-09T14:43:47.023 に答える