0

なぜこのクエリの実行が遅いのか疑問に思っていました。誰かがそれがどのように処理されたかを私に教えてくれるなら、それは素晴らしいことです。照会されるDBには5億を超える行があります。このクエリは、TOP 10が完了するのに非常に時間がかかるほど不十分に記述されているのでしょうか?月+年ごとにデータをクエリしたい場合、クエリをどのように改善できますか?

 SELECT TOP 10 *
 FROM ADB.dbo.Stuff tt
 WHERE MONTH(tt.SomeDate) = 5
 AND
 YEAR(tt.SomeDate) = 2011

SELECT TOP 10は、10件の結果が得られた後、停止するだけではありませんか?それとも、500m以上の列を通過している間、まだ私の状態が見つからないため、それほど時間がかかりますか?

このような簡単な質問に感謝し、申し訳ありません。

4

1 に答える 1

7

MONTH(column)と はサージ可能ではないため、テーブル全体をスキャンするYEAR(column)必要があり、 SQL Server に の意味を伝えていませんTOP。10行が見つかった場合、SQL Serverが短絡できる可能性があるのは事実ですが、それが発生した場合、スキャンがはるかに進んでいる可能性があり、違いは最小限です。これは特に、where 句に一致する行が 0 行または 10 行未満の場合に当てはまります。

はるかに優れたWHERE条項は次のとおりです。

WHERE SomeDate >= '20110501' AND SomeDate < '20110601';

文字列を構築したくない場合は、それらをパラメーター/変数として渡し、次のようにします。

DECLARE @year INT;
DECLARE @month INT;

SET @year = 2011;
SET @month = 5;

...
WHERE SomeDate >= DATEADD(MONTH, @month-1, DATEADD(YEAR, @year-1900, '19000101'))
  AND SomeDate <  DATEADD(MONTH, @month,   DATEADD(YEAR, @year-1900, '19000101'));

いずれの場合も、 にインデックスがあればSomeDate、それを使用でき、テーブル スキャンを回避できます。10 行しか探していなくても、ショート サーキットが発生する可能性がある場合でも、5 億行のテーブルでのテーブル スキャンは避けたいと考えています。

ただし、テーブル スキャンがなくても、このクエリは依然として非効率的です。本当にすべての列が必要ですか? インデックスSomeDateが使用されている場合でも、残りの列を取得するために、シークでクラスター化インデックスまたはカバリング インデックスを検索する必要があります。これらの列が必要ない場合は、含めないでください。

bluefeet が指摘したように、 SQL Serverにどの10 を意味するかTOP 10を伝えていない場合、このようなことは意味がありません。が適切なインデックスを使用する場合は、とにかく使用しないことで回避していると思われる追加のコストのかかる並べ替え演算子を回避できます。ORDER BYORDER BYORDER BY

于 2012-08-14T21:51:08.690 に答える