サブクエリを使用して、一致するフィールドを持つすべての以前のレコードの合計数を検索する場合、5万件のレコードがあるテーブルでパフォーマンスはひどいです。サブクエリがなければ、クエリは数ミリ秒で実行されます。サブクエリを使用すると、実行時間は1分以上になります。
このクエリの場合、結果は次のようになります。
- 特定の日付範囲内のレコードのみを含めます。
- 日付範囲に関係なく、現在のレコードを含まない、以前のすべてのレコードのカウントを含めます。
基本的なテーブルスキーマ
Activity
======================
Id int Identifier
Address varchar(25)
ActionDate datetime2
Process varchar(50)
-- 7 other columns
サンプルデータ
Id Address ActionDate (Time part excluded for simplicity)
===========================
99 000 2017-05-30
98 111 2017-05-30
97 000 2017-05-29
96 000 2017-05-28
95 111 2017-05-19
94 222 2017-05-30
推測される結果
日付範囲のため2017-05-29
に2017-05-30
Id Address ActionDate PriorCount
=========================================
99 000 2017-05-30 2 (3 total, 2 prior to ActionDate)
98 111 2017-05-30 1 (2 total, 1 prior to ActionDate)
94 222 2017-05-30 0 (1 total, 0 prior to ActionDate)
97 000 2017-05-29 1 (3 total, 1 prior to ActionDate)
レコード96および95は結果から除外されますが、PriorCount
サブクエリに含まれます
現在のクエリ
select
*.a
, ( select count(*)
from Activity
where
Activity.Address = a.Address
and Activity.ActionDate < a.ActionDate
) as PriorCount
from Activity a
where a.ActionDate between '2017-05-29' and '2017-05-30'
order by a.ActionDate desc
現在のインデックス
CREATE NONCLUSTERED INDEX [IDX_my_nme] ON [dbo].[Activity]
(
[ActionDate] ASC
)
INCLUDE ([Address]) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
)
質問
- このクエリのパフォーマンスを向上させるためにどのような戦略を使用できますか?
編集1
DBで何を変更できるかという質問に対する回答として、テーブル構造だけでなく、インデックスを変更できます。
編集2列に
基本的なインデックスを追加しましたAddress
が、あまり改善されていないようです。私は現在、一時テーブルを作成し、値なしで値を挿入PriorCount
し、特定のカウントで各行を更新することで、はるかに優れたパフォーマンスを見つけています。
編集3
インデックススプールジョーオブビッシュ(受け入れられた答え)が見つかったことが問題でした。新しいを追加nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
すると、一時テーブルを使用せずにクエリ時間が1分以上から1秒未満に短縮されました(編集2を参照)。
nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
と、クエリ時間は1分以上から1秒未満に短縮されました。可能であれば+10。ありがとう!