2016-08-03 10 views
1

私はいくつかのクエリの最適化に取り組んでおり、説明する方法がわかりません。次のコードでSQL Server 2012の使用: TSQL:静的変数とwhere句の計算

DECLARE @startdate DATETIME2 = DATEADD(day,-1,GETDATE()), 
     @enddate DATETIME2 = GETDATE() 

SELECT * 
FROM table1 WITH(NOLOCK) 
WHERE somedate BETWEEN DATEADD(day,-1,GETDATE()) AND GETDATE() 
    AND somestate = 'NV' 

SELECT * 
FROM table1 WITH(NOLOCK) 
WHERE somedate BETWEEN @startdate AND @enddate 
    AND somestate = 'NV' 

は、実際の実行計画を見ると、第1の選択は、インデックスが求め有し、第2クラスタード・インデックス・スキャンを持っているキーのルックアップ、。 SELECTは機能的な目的と本質的に同じなので、なぜ実行計画に違いがあるのか​​わかりませんでした。私の最後のDBAは、 WHERE節で値を持つ変数を宣言するのが WHERE節の計算よりも優れていると言いましたが、これはそのステートメントに反すると思われます。私は2つのステートメントの間に大きな格差を引き起こす原因を明確にすることを望んでいます。私はこれについてのいくつかの答えを検索しようとしましたが、多くの運がなかった、誰かが正しい方向に私を指すことができれば、私は非常に感謝するだろう。

ありがとうございました!

+0

[NOLOCKをどこにでもぶつける習慣が悪い](http://blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere/) - これはどこにでも使うことをお勧めしません。反対! –

+0

2番目のケースでは、SQL Serverはstartdateとenddateが関連していることを認識していないと思うので、彼は任意の値を期待しているので、スキャンを選択します。 –

答えて

0

where節での計算の使用が有害であると思われる場合、あなたは少し誤解していると思います。インデックス作成に使用される列を含む計算を使用するのは、計算でインデックスシークを効果的に実行できないため、パフォーマンスの問題が発生した場合です。あなたの例では、索引付けの列(いつか)は計算に含まれていないので、索引付けに悪影響を及ぼすべきではありません。 SARGの詳細については、Sql Server Query Performanceを参照してください(WHERE句の計算を参照している問題)。

実行計画をSSMSで表示している場合は、シークとは対照的にクラスタ化スキャンを実行する2番目の計画では、より最適なインデックスを作成する必要があると思われるため、あなたの質問のために。

最後に、キールックアップが表示されるのは、通常、クエリが最適化されていないことを示します(Key Lookup Showplan Operator)。

パフォーマンスの低いノートでは、実際にあなたの状況に当てはまるとは思えませんが、偶発的な重複を避けるために、日付間ではなく> = < =を使用することをお勧めします。

+0

アンソニーの情報をありがとうございます。これらの選択肢の最初のバージョンは、節の一部としてsomestateを持たず、可変バージョンがクラスタード・インデックス・スキャンを行い、計算を伴うものがなかったし、いずれも示唆されていなかった私は変数の導入がインデックススキャンをどのように強制するかわからないので、私にはもっと混乱していました。そして面白いことに、somestateを含む新しいバージョンには、変数バージョンのインデックスがありませんが、計算されたバージョンはありません。 – Xiphoen