客户端报告了执行存储过程时重复出现的非常奇怪行为的实例。
他们具有运行易失数据集的缓存转置的代码。如果满足以下条件,则写入存储的proc以按需重新处理数据集: 1.自上次重新处理以来数据集已更改 2.数据集5分钟未更改。
(第二个条件在更改期间停止了重复的大规模重新计算。)
这可以正常工作几个星期,SP花费1-2秒来完成重新处理,并且仅在需要时才执行。然后…
现在已经重复了很多很多次。SP突然“停止工作”,再也没有返回,并且客户端超时。(我们尝试通过Management Studio运行它,并在15分钟后取消了查询。)
但是,每次我们重新编译SP时,它突然又可以工作了。
我尚未在适当的EXEC语句上尝试使用RECOMPILE,但是我尤其不希望以任何方式这样做。它每小时被调用数百次,通常什么也不做(它每天只对数据进行几次重新处理)。如果可能的话,我想避免重新编译相对复杂的SP的开销,“只是为了避免“不应”发生的事情…
干杯, Dems。
编辑:
伪代码如下:
这些选择“不是很漂亮”,但是当它们在线执行时,它们会立即执行。包括SP拒绝完成的时间。探查器显示它是SP在“插入”处的INSERT。
SP没有参数,并且sp_lock没有显示任何阻塞进程的信息。
就像其他人所说的那样,有关数据或源表统计信息的更改方式的某些问题使缓存的查询计划变得陈旧。
WITH RECOMPILE可能是最快的修复方法-用于SET STATISTICS TIME ON在不立即使用之前找出重新编译的实际费用。
WITH RECOMPILE
SET STATISTICS TIME ON
如果这仍然不是可接受的解决方案,那么最好的选择可能是尝试重构insert语句。
您没有在说您正在使用UNION还是UNION ALL在插入语句中说。我见过INSERT INTO有UNION产生一些奇怪的查询计划,特别是在2005年SQL预SP2版本。
UNION
UNION ALL
INSERT INTO
Raj提出的删除和重新创建目标表的建议 SELECT INTO是一种解决方法。
SELECT INTO
您也可以尝试将三个源查询中的每一个选择到它们自己的临时表中,然后将UNION这些临时表一起插入。
或者,您可以尝试将这些建议组合使用-将联合的结果放入带有的临时表中SELECT INTO,然后将其插入目标表中。
我已经看到所有这些方法都可以解决类似情况下的性能问题。测试将揭示哪些数据可以提供最佳结果。