当使用子查询查找具有匹配字段的所有先前记录的总数时,在只有5万条记录的表上,性能会很糟糕。没有子查询,查询将在几毫秒内执行。使用子查询,执行时间超过一分钟。
对于此查询,结果必须:
- 仅包括给定日期范围内的那些记录。
- 包括所有先前记录的计数,不包括当前记录,无论日期范围如何。
基本表架构
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
发现问题的索引后台处理程序Joe Obbish(可接受的答案)。一旦添加了新内容nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
,查询时间就从一分钟以上减少到不到一秒,而无需使用临时表(请参见编辑2)。
nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
的查询,查询时间就会从一分钟以上减少到不到一秒钟。如果可以的话,+ 10。谢谢!