生成SQL查询计划需要5分钟,查询本身以毫秒为单位运行。什么';什么事?
我有一个在SQLServer2008上运行的相当复杂(或丑陋,取决于您的看法)的存储过程。它基于一个具有pk表和fk表的视图来进行大量的逻辑。fk表与pk表的左连接次数略多于30次(fk表的设计很差-它使用名称-值对,我需要将其展平。不幸的是,它是第三方,我无法更改) 无论如何,它已经运行了好几个星期了,直到我周期性地注意到运行需要3-5分钟。事实证明,这就是生成查询计划所需的时间。一旦查询计划存在并被缓存,存储过程本身就会非常高效地运行。在有理由重新生成和缓存查询计划之前,一切都会顺利进行生成SQL查询计划需要5分钟,查询本身以毫秒为单位运行。什么';什么事?,sql,sql-server,tsql,sql-server-2008,stored-procedures,Sql,Sql Server,Tsql,Sql Server 2008,Stored Procedures,我有一个在SQLServer2008上运行的相当复杂(或丑陋,取决于您的看法)的存储过程。它基于一个具有pk表和fk表的视图来进行大量的逻辑。fk表与pk表的左连接次数略多于30次(fk表的设计很差-它使用名称-值对,我需要将其展平。不幸的是,它是第三方,我无法更改) 无论如何,它已经运行了好几个星期了,直到我周期性地注意到运行需要3-5分钟。事实证明,这就是生成查询计划所需的时间。一旦查询计划存在并被缓存,存储过程本身就会非常高效地运行。在有理由重新生成和缓存查询计划之前,一切都会顺利进行 有
有人见过这个吗?为什么制定计划需要这么长时间?有没有办法让它更快地制定计划 您可以尝试使用一个。计划生成仍将持续一段时间,但应该会大大缩短。您是否考虑过像这样将您的30加入选择重新写入smth
SELECT [key], NULL AS [a], NULL AS [b]
INTO #temp
FROM [pk-table]
UPDATE t SET t.[a] = fk.[a], t.[b] = fk.[b]
FROM #temp t
INNER JOIN (
SELECT f.[key],
MAX(CASE WHEN f.[name] = 'a' THEN f.[value] ELSE NULL END) AS [a],
MAX(CASE WHEN f.[name] = 'b' THEN f.[value] ELSE NULL END) AS [b]
FROM [fk-table] f
GROUP BY f.[key]
) fk ON (fk.[key] = t.[key]
虽然这可能不是您最初问题的答案:)但某些因素会导致计划需要重新编译,例如统计数据更新或DDL更改。 列表如下所示: 当前形式的查询总是需要3-5分钟才能重新编译:这是不可避免的 假设您无法更改它(透视、使用触发器维护“正确”的表等),那么您只能控制重新编译的发生时间
雷姆斯的计划指南答案是一种方式。我还会查看我的统计维护,并确保它是在一夜之间完成的,比如说,所以它只在一天开始时发生一次谢谢。我尽量避免使用计划指南,除非我真的不得不这样做。一夜之间强制统计是一个很好的解决方案。此外,我们还考虑过尝试使用触发器。我们还不清楚桌子上的实际负载,因为它还不是一个带电系统。但我想试试。这也值得一试。虽然我尝试过PIVOT和一些CTE,但到目前为止,作为视图的左侧连接是最有效的。你以前见过这样更快吗?见过。我有相同的逻辑(多个(大约20个)“fk表”左连接到一个“主表”),在添加同一个表的另一个连接后,执行时间显著增加。重新编写巨大的一步选择到两步选择更新真的很有帮助。但也许这只是不幸指数的一个特殊情况,我没有去挖掘。(很抱歉,您的帖子中遗漏了“on a view”语句)np-视图只是简化了查询的重用,我不确定这是否必要。为什么生成计划需要这么长时间?部分是在查询优化过程中考虑的组合数。一个30个连接选择有30个!(30阶乘)考虑不同的接合顺序,或约2.65 e32。而订单只是查询优化的一个方面来考虑。按照Rad的建议,将查询分解成更小的部分,将子结果存储在临时表中,可以大大减少优化工作,但可能会给出更慢的计划。通过删除连接并在查询的select子句中进行选择,我可以将执行计划时间缩短到3秒。