SQL 筛选最近的行时查询需要很长时间
SQL Query takes a long time when filtering recent rows
我有这个 SQL 查询,但我发现 运行 最多可能需要 11 秒。我真的很困惑,因为当我将日期选择更改为 2018 年日期时,它立即 returns。
查询如下:
select
cv.table3ID, dm.Column1 ,dm.Column2, mm.Column1,
convert(varchar, cv.Date, 107) as Date,
mm.table2ID, dm.table1ID, mm.Column2,
count(ctt.table4ID) as Total
from
table1 dm
inner join
table2 mm on mm.table2ID = dm.table1ID
inner join
table3 cv on cv.table3ID = mm.table2ID
left join
table4 ct on ct.table4CVID = cv.table3ID
inner join
table4 ctt on ctt.table4MMID = mm.table2ID
where
ctt.table4Date >= '2019-01-19'
and ct.table4CVID is null
and dm.Column1 like '%Albert%'
and cv.Column1 = 39505
and cv.Status = 'A'
group by
cv.table3ID, dm.Column1 ,dm.Column2, mm.Column1,
cv.Date, mm.table2ID, dm.table1ID, mm.Column2
我发现当我使用 ctt.table4Date >= '2018-01-19' 执行该查询时,响应是即时的。但是对于“2019-01-19”,它需要 11 秒。
最初,当我发现查询耗时 11 秒时,我认为这一定是索引问题,但我不确定它是否与索引有关,因为它对较旧的系统执行得很好日期。
我查看了具有不同日期的查询的执行计划,它们看起来完全不同。
关于为什么会发生这种情况有什么想法吗?跟更新统计有关系吗?
[更新]
下图是table4 ctt在2018年和2019年的执行计划对比。根据执行计划,2018年占运营商成本的43%,2019年占45%。
Execution Plan comparison of table4 ctt 2019 and 2018. Top is 2019, bottom is 208
这里的图片是table4 as ct再次执行计划的对比。同样在这里,顶部是 2019 年,底部是 2018 年。
Execution plan of table4 ct comparison 2019 and 2018. Top is 2019, bottom is 208
[更新 2]
以下是 SQL 执行计划:
使用“2018-01-19”作为日期时:https://www.brentozar.com/pastetheplan/?id=SyUh8xXQV
使用“2019-01-19”作为日期时:https://www.brentozar.com/pastetheplan/?id=rkELW1Q7V
问题很可能是从其他 table 返回更多行。您与 [更新] 链接的聚集索引扫描仅显示聚集索引搜索。
但是,您确实需要意识到调用索引查找的次数是 144 次。实际读取的行数是 8 位数字,这导致响应缓慢。
我猜当这对你来说工作正常时,这个 table 的实际执行次数将是 1。144 在这里杀了你;给穷求谓词。如果您知道适用于您的查询计划,并且索引已经存在以支持它,您应该 forceseek 计划并给出明确的提示以按特定顺序加入。
编辑
查看共享计划,将日期更改为 2018 年对您来说效果更快,因为考虑到正在处理的数据量,SQL 切换到使用哈希匹配代替循环连接。
我有这个 SQL 查询,但我发现 运行 最多可能需要 11 秒。我真的很困惑,因为当我将日期选择更改为 2018 年日期时,它立即 returns。
查询如下:
select
cv.table3ID, dm.Column1 ,dm.Column2, mm.Column1,
convert(varchar, cv.Date, 107) as Date,
mm.table2ID, dm.table1ID, mm.Column2,
count(ctt.table4ID) as Total
from
table1 dm
inner join
table2 mm on mm.table2ID = dm.table1ID
inner join
table3 cv on cv.table3ID = mm.table2ID
left join
table4 ct on ct.table4CVID = cv.table3ID
inner join
table4 ctt on ctt.table4MMID = mm.table2ID
where
ctt.table4Date >= '2019-01-19'
and ct.table4CVID is null
and dm.Column1 like '%Albert%'
and cv.Column1 = 39505
and cv.Status = 'A'
group by
cv.table3ID, dm.Column1 ,dm.Column2, mm.Column1,
cv.Date, mm.table2ID, dm.table1ID, mm.Column2
我发现当我使用 ctt.table4Date >= '2018-01-19' 执行该查询时,响应是即时的。但是对于“2019-01-19”,它需要 11 秒。
最初,当我发现查询耗时 11 秒时,我认为这一定是索引问题,但我不确定它是否与索引有关,因为它对较旧的系统执行得很好日期。
我查看了具有不同日期的查询的执行计划,它们看起来完全不同。
关于为什么会发生这种情况有什么想法吗?跟更新统计有关系吗?
[更新]
下图是table4 ctt在2018年和2019年的执行计划对比。根据执行计划,2018年占运营商成本的43%,2019年占45%。 Execution Plan comparison of table4 ctt 2019 and 2018. Top is 2019, bottom is 208
这里的图片是table4 as ct再次执行计划的对比。同样在这里,顶部是 2019 年,底部是 2018 年。 Execution plan of table4 ct comparison 2019 and 2018. Top is 2019, bottom is 208
[更新 2]
以下是 SQL 执行计划:
使用“2018-01-19”作为日期时:https://www.brentozar.com/pastetheplan/?id=SyUh8xXQV
使用“2019-01-19”作为日期时:https://www.brentozar.com/pastetheplan/?id=rkELW1Q7V
问题很可能是从其他 table 返回更多行。您与 [更新] 链接的聚集索引扫描仅显示聚集索引搜索。
但是,您确实需要意识到调用索引查找的次数是 144 次。实际读取的行数是 8 位数字,这导致响应缓慢。
我猜当这对你来说工作正常时,这个 table 的实际执行次数将是 1。144 在这里杀了你;给穷求谓词。如果您知道适用于您的查询计划,并且索引已经存在以支持它,您应该 forceseek 计划并给出明确的提示以按特定顺序加入。
编辑
查看共享计划,将日期更改为 2018 年对您来说效果更快,因为考虑到正在处理的数据量,SQL 切换到使用哈希匹配代替循环连接。