2016-11-17 12 views
2

以下のクエリを実行すると、ほぼ2.30分かかります。日付でチェックするとSQL Server 2014が非常に遅く動作するのはなぜですか?

select Clientid, 
     Sum(Qty * Rate) BuyVolume 
from Table1 S(nolock) 
    join table2 T on T.ReferrentClientId = S.Clientid 
where S.Column2 = 'B' 
and S.Date >= T.Date 
and S.Date <= T.Date +30 
Group by Clientid 

しかし、私がT.Dateを '2016-12-23 00:00:00.000'とした場合、結果は1秒で取得されます。

select Clientid, 
     Sum(Qty * Rate) BuyVolume 
from Table1 S(nolock) 
    join table2 T on T.ReferrentClientId = S.Clientid 
where S.Column2= 'B' 
and S.Date >= '2015-12-23 00:00:00.000' 
and S.Date <= '2016-01-22 00:00:00.000' 
Group by Clientid 

表1には47589000行が含まれ、表2には5行のみが含まれています。 結果セットには2つの行しか含まれていません。どちらの日付列も日時形式です。

私の実行をスピードアップする方法はありますか?

+4

実行計画とインデックスの詳細を投稿できますか? – GarethD

+3

ロックテーブルのヒントは使用しない理由がありますが、[この記事](https://blogs.sentryone.com/aaronbertrand/bad-habits-nolock-everywhere/)では、 。 TL/DR; NoLockは、基礎となるデータと一致しない結果を返すことができます。 –

+0

日付比較を 'WHERE'から' ON'節に移動すると助けになりますか? –

答えて

1

違いは明らかにどのようにクエリが最適化されているかです。詳細な情報を得るには、実行計画を見てください。

これはあなたのクエリです:

select Clientid, Sum(Qty*Rate) as BuyVolume 
from Table1 S join 
    table2 T 
    on T.ReferrentClientId = S.Clientid 
where S.Column2 = 'B' and 
     S.Date >= T.Date and 
     S.Date <= T.Date + 30 
Group by Clientid; 

最初の提案はTable1(Column2, Date, ClientId)のインデックスです。

しかし、table2は非常に小さいので、実際にはjoinの運転台にしたいと思っています。それはTable1(ClientId, Column2, Date)の代替インデックスを示唆しています。これは最初にjoinを実行する必要があります。これにより、処理される行数が大幅に削減されます。

+0

フィールド(Column2、Date、ClientId)を持つTable1にはすでに索引があります。そして私は結合順序を変更しました。しかし結果はありません.. !! –

+0

日付フィールドのカーディナリティが高く、ClientIDのカーディナリティが低い場合、テーブルのサイズに関係なく、最初のインデックスの有用性が損なわれませんか? – MatBailie

+2

@bino:この回答は、あなたが持っているインデックスを使用せず、むしろ別の順序で列をインデックス付けすることを提案しています(最も重要なのは日付です)。 – MatBailie

0

ここで何が起こっているのかについては、最初のクエリではWHERE句では、結合の各レコードの値がDateである必要がありますが、2番目のクエリではこれは起こる必要はありません。 1つ目の可能性は、クエリオプティマイザが、2番目のクエリのWHERE句の実行中にtable2の値を参照する手順を完全にスキップしていることです。

WHERE句はGROUP BYの前に実行されるため、これらのクエリはWHERE句以外は同じように見えることに注意してください。

+5

匿名のdownvotesは無礼であり、誰にも恩恵を受ける。フィードバックをお寄せください、ありがとうございます。 –

0

これを試してください。

select Clientid, 
     Sum(Qty * Rate) BuyVolume 
from Table1 S(nolock) 
    join table2 T on T.ReferrentClientId = S.Clientid 
where S.Column2 = 'B' 
and S.Date between T.Date and T.Date + 30 
and S.Date between (select min(Date) from table2) and (select max(Date) from table2) + 30 
Group by Clientid 
0

ここからのさまざまな提案によると、私はNONCLUSTERED INDEXを以下のように作成しました。

create NONCLUSTERED index myIndex 
on Table1(Column2) include (Date,Clientid,qty,rate) 

ここで結果を得るのに7秒しかかかりません。すべての回答とコメントをありがとう。

関連する問題