动态查询导致高CPU和内存利用率

时间:2016-10-27 07:49:06

标签: sql-server full-text-search sqlperformance

我在Windows Server 2012中使用SQL Server 2014 Enterprise。

我已检查Min并且Max Allocated Memory for SQL Server已正确配置。

昨天,用户多次并行报告并收到大量警报(高CPU和高内存)。从下面的查询中,我发现顶级CPU使用了查询:

...
...
FROM sys.dm_exec_query_stats AS qs  
cross apply sys.dm_exec_sql_text(qs.sql_handle) AS st  
cross apply sys.dm_exec_query_plan (qs.plan_handle) AS qp 
ORDER BY (total_worker_time/execution_count) desc, qs.last_execution_time DESC

我发现前10个查询完全相同,只是WHERE子句中的更改很少。 execution_count = 1表示所有查询。查询将记录插入到#temp表中,格式如下:

Insert into #Temp(col1, col2,............)
Select
.
.
From
(
Select
.
.
Where (CONTAINS(val1, ' "xx1*" ') OR CONTAINS(val2, ' "yy1*" ') OR CONTAINS(val3, ' "zz1*" ')..........30-35 CONTAIN blocks)
-- here "xx*", "yy*" values are changing in each query (I guess this is due to parameter selection by end users)
) x

如果这些动态查询是罪魁祸首,那么解决方案是什么(因为用户不会停止运行查询)?

我可以要求将报告查询转换为SP吗? 如何避免我得到的不同执行计划?

我手动杀死了高度利用的查询,但这不是解决方案。

寻求帮助。

更新

我再也看不到任何内存问题了。但CPU仍然达到100%。

我观察到上述特定查询(在报告中使用)经常由用户访问,并且当此查询运行时CPU利用率达到100%。它经常发生。 WHERE子句根据用户的报告参数选择每次执行都会更改(我不知道报告的设计方式或参数的传递方式)。

此外,我已检查表统计信息(每天更新),索引正确定义。基表处理超过3百万行(val1,val2 ...在CONTAIN中使用属于此表)。

调整此查询的方法有哪些?

2 个答案:

答案 0 :(得分:1)

显然你的SQL语句没有被缓存,因此你每次都会得到一个新的执行计划。并查看您的代码(除非您已经省略了其他一些块),这可能是因为如果WHERE中的CONTAINS子句。

我的建议是将这些语句转换为存储过程并从WHERE中删除CONTAINS,并通过INNER JOIN到CONTAINSTABLE(...)来完成。看看您是否设法在这些更改后缓存查询。

对于高CPU / RAM使用率,您说用户并行运行报告,因此这听起来像锁定问题。尝试将WITH NOLOCK提示添加到SELECT语句中,看看它是如何进行的。

您也没有说明您的报告声明对哪些数据进行了操作。你在选择数百万条记录吗?由于各种一对多或类似的连接,您是否获得记录乘法?请评论。

<强>更新

在OP表示该查询适用于具有3M +记录的表格并且有大约30-35个全文搜索条件后,主要建议是:

  1. 重新设计查询/ db结构以降低SQL复杂性和CONTAINS子句的数量。
  2. 将此查询从实时执行的用户查询转换为某些夜间报告,这将创建向用户显示的较小的预先计算结果数据集。
  3. 考虑使用外部搜索引擎执行此任务,例如Solrelasticsearch。但这需要熟悉它们的工作方式,并且您将无法将其搜索结果输出直接连接到SQL级别的其他表。您必须从代码(C#或Java,或者您使用的任何东西)调用这些搜索引擎。

答案 1 :(得分:0)

我想建议启用服务器级别配置:“针对临时工作负载进行优化”

sp_configure 'optimize for ad hoc workloads',1
GO
reconfigure
go