2017-03-24 15 views
2

私は自分で見つけることができなかったので、(私はそれを検索する方法がわからないため)何かの説明が必要です。SQLクエリ変数とハードコードされた値の比較

いくつかのCommon Table Expressionsを持つSQL Serverクエリがあります。これらのCTEの1つは、日付とユーザーがnullでないことに基づいてデータを選択しています。

WHERE 
    "dummy"."UsageEnd" >= '20161001' 
    AND "dummy"."UsageEnd" < '20161101' 
    AND "Users"."Login" IS NOT NULL 

この形式では、このクエリは約2秒で実行されますが、このクエリは非常に一般的に実行されるため、パラメータに変更する必要があります。しかし、私はそれを変更した場合:リマインダーとして(

declare @datestart datetime 
set @datestart = '20161001'; 

declare @dateend datetime 
set @dateend = '20161101'; 

このサブクエリは、23〜24秒で実行し、全体の問合せこのサブクエリを:@start@endはどちらかdatetimeまたはvarcharとして宣言されている

WHERE 
    "dummy"."UsageEnd" >= @start 
    AND "dummy"."UsageEnd" < @end 
    AND "Users"."Login" IS NOT NULL 

以前は12〜15秒かかっていたときに7〜8分かかります)。

日付を変数と比較すると実行時間が非常に劇的に向上する理由を誰かに説明できますか?また、CTEが変数である場合には、1つではなく毎回それを再評価するため、クエリ全体が長時間かかる可能性もあります。

+0

実行計画を比較しましたか? – jarlh

+3

おそらくパラメータスニッフィングと関係があります。あなたがそれを検索するなら、私が与えることができるよりも優れた説明と解決策を見つけるでしょう。あなたは 'RECOMPILE'ヒントを試してみることもできます。 – HoneyBadger

+5

**固定値**を日付リテラルとして指定すると、SQL Serverはこの正確な日付値**のクエリを最適化できます。 **パラメータ**を指定した場合、SQL Serverは可能な限り最適な実行計画**をパラメータ値として提供する可能性のある日付値**に対応させる必要があります。別の実行計画 –

答えて

0

問題がうまくみんなのコメントの組み合わせによって発生する可能性がありますあなたのUsageEnd列がdatetimeデータ型ではなく、varchar型は、オプティマイザは最初の順序でのdatetime型にすべての値を変換する必要があります場合は

変数との比較を行います。

「ハードコードされた定数」を持つ最初のクエリはすでにvarcharにあるため、オプティマイザは比較を高速に実行できます。

両方の計画が異なって見え、問題の原因を明確に示しています。

+0

UsageEnd列はdatetime型です。そのため、「ハードコードされた」varcharと比較すると、はるかに迅速でした。残念ながら、実行計画に関しては、私はそれらを比較することができません。現在、私はそのDB(SHOWPLAN権限が拒否されている)への読み取りアクセスしか持っていないためです。私の会社を知っている人なら誰も私にはより高いレベルのアクセス権を与えることはできないので、私はこれを分析することができません。しかし、HoneyBadger(OPTION(RECOMPILE))が提案した解決策は魅力的でした。 :) – Krzywusek

+0

あなたは解決策を見つけましたか? –

+0

また、私自身の経験では、CTEを使用するときにクエリオプティマイザが少しの助けを必要とすることがあります。あまりにも複雑なクエリオプティマイザは、最適ではないクエリプランを生成することがあります。それらのうちのいくつかを一時テーブル(@または#)に変換してから、次のCTEでそれらのテーブルを使用すると、私には印象的なスピードの向上がもたらされました。 –

0

演算子が異なるデータ型の2つの式を結合する場合、データ型の優先順位の規則は、優先順位の低いデータ型が優先順位の高いデータ型に変換されるように指定します。変換がサポートされている暗黙の変換でない場合、エラーが戻されます。 MSDN

関連する問題