Sql server SQL Server查询占用100%的CPU并运行数小时

Sql server SQL Server查询占用100%的CPU并运行数小时,sql-server,performance,Sql Server,Performance,我有一个查询,已经每天运行了2年多一点了,通常不到30秒就完成了。突然,昨天,查询开始需要3个多小时才能完成,整个时间都在使用100%的CPU SQL是: SELECT @id, alpha.A, alpha.B, alpha.C, beta.X, beta.Y, beta.Z, alpha.P, alpha.Q FROM [DifferentDatabase].dbo.fnGetStuff(@id) beta INNER JOIN vwSomeData a

我有一个查询,已经每天运行了2年多一点了,通常不到30秒就完成了。突然,昨天,查询开始需要3个多小时才能完成,整个时间都在使用100%的CPU

SQL是:

SELECT
  @id, 
  alpha.A, alpha.B, alpha.C, 
  beta.X,  beta.Y,  beta.Z, 
  alpha.P, alpha.Q
FROM 
  [DifferentDatabase].dbo.fnGetStuff(@id) beta 
  INNER JOIN vwSomeData alpha ON beta.id = alpha.id
alpha.id是一个BIGINT类型,beta.id是一个INT类型。dbo.fnGetStuff是一个简单的SELECT语句,在同一个DB中的表上有两个内部联接,使用WHERE id=@id。该函数返回大约11000个结果

view vwSomeData是一个简单的SELECT语句,包含两个内部联接,返回大约590000个结果

当视图和功能自行执行时,将在不到10秒内完成。首先将函数的结果选择到一个临时表中,然后加入,这使得查询在<10秒内完成


如何排除故障?我在活动管理器中没有看到任何锁。

我在连接返回大型数据集的函数时遇到过类似的问题。我必须按照你的建议去做。将结果放在临时表中,并在临时表上联接。

您可以使用SQL Server探查器工具来监视SQL Server上正在运行的查询。它不显示锁,但它还可以通过建议索引提示您如何改进查询。

查看查询计划。我猜执行计划中有一个或多个表扫描。这将对结果中的少数记录造成大量I/O

如果您有一个合理的最新版本的SQLServerManagementStudio,那么它在“工具”下也有一个数据库调优顾问。它从探查器中获取跟踪信息,并提出一些有时非常有用的建议。确保没有太多的查询-构建建议需要很长时间


我不是这方面的专家,但过去在这方面有过一些运气。

看看估计的计划,这可能会有所启发。通常,当查询成本变得更高几个数量级时,这是因为在哈希连接更合适的地方使用循环或合并连接。如果在估计的计划中看到循环或合并联接,请查看它预期要处理的行数—它是否远小于您知道实际要处理的行数?您还可以指定一个使用散列联接的提示,并查看它是否执行得更好。如果是这样,请尝试更新统计信息,并查看它是否返回到没有提示的哈希联接

SELECT
  @id, 
  alpha.A, alpha.B, alpha.C, 
  beta.X,  beta.Y,  beta.Z, 
  alpha.P, alpha.Q
FROM 
  [DifferentDatabase].dbo.fnGetStuff(@id) beta 
  INNER HASH JOIN vwSomeData alpha ON beta.id = alpha.id

-不知道有什么样的模式,只是想抛开一些想法:

就像其他人说的。。。使用探查器并找到疼痛的来源。。。但我认为这是另一个数据库上的函数。由于该函数可能会带来痛苦,您是否考虑过对[DifferentDatabase]进行一点反规范化或其他处理。我认为,与代价高昂的函数相比,使用索引连接到更平坦的表时,您会发现更具可伸缩性。

运行以下命令:

将SHOWPLAN\u设置为全部打开


然后运行查询。它将显示执行计划,查找索引或表上的扫描。这很可能就是您的查询现在发生的情况。如果是这样的话,试着弄清楚为什么它现在不使用索引刷新统计信息,等等。你需要使用函数吗?可以将整个过程重新写入存储过程中,并在其中作为参数传入@ID

即使您的表有索引,因为您将@ID作为变量传递给WHERE子句,这可能会大大增加查询的运行时间

不使用索引的原因是,查询分析器在选择访问方法执行查询时不知道变量的值。因为这是一个批处理文件,所以Transact-SQL代码只传递了一次,这使得查询优化器无法知道选择使用索引的访问方法需要知道什么

如果您不能重写SQL.

,您可能需要考虑索引查询提示。
由于这种情况刚刚开始发生,索引也可能变得支离破碎,可能需要重建。

我见过太多使用表值函数的情况,因为我可以。最好保持简单。并尝试分解视图。在SQL Server中,当对象依赖关系变得混乱时,会发生有趣的事情。