【问题标题】:Dynamic Query causing High CPU and Memory utilization动态查询导致 CPU 和内存使用率过高
【发布时间】:2016-10-27 07:49:05
【问题描述】:

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

我检查了MinMax 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 子句根据用户选择的报告参数在每次执行时发生变化(我不知道报告的具体设计方式或参数是如何传递的)。

此外,我检查了表格统计信息(每天都会更新),索引正确定义。基表处理超过 300 万行(在 CONTAIN 中使用的 val1、val2...属于该表)。

调整这个查询的方法是什么?

【问题讨论】:

  • How can I avoid the different execution plans that I am getting?..你能贴几个吗..
  • 可能是您的内存被拉伸到了最大值,并且涉及(虚拟)内存交换。您的查询将无法从缓存命中中受益,这会大大减慢速度。
  • 您在val 列上定义了正确的全文索引?
  • @TT - 我对查询的目的不太了解。我怎样才能检查它?还有,我如何查看memory is stretched to the max and there is (virtual) memory swapping involved
  • @p2k 只是好奇您是否有运气优化您的查询。您是否设法加快了速度?

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


【解决方案1】:

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

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

关于高 CPU/RAM 使用率,您说用户正在并行运行报告,所以这听起来像是一个锁定问题。尝试将WITH NOLOCK 提示添加到您的 SELECT 语句中,看看效果如何。

您也没有说明您的报告报表操作的数据量。您是否选择了数百万条记录?您是否因为各种一对多或类似的连接而获得记录乘法?请发表评论。

更新:

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

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

【讨论】:

  • Ew WITH NOLOCK 可能导致脏读、丢失行、读取行两次等...我根本不建议报告...参见:Bad habits : Putting NOLOCK everywhere
  • 我看到有 30-35 个 CONTAINS 块,例如 CONTAINS (val1, ' "xx*" ') OR CONTAINS (val2, ' "xx1*" ') OR........。该查询的表包含超过 300 万条记录。
  • @TT。我们不是在谈论将它放在任何地方,检查答案文本,我建议尝试将它放置,看看是否有改进。不要盲目接受不良习惯提示,它是不良编码奖章的反面。由于某些原因,SQL Server 开发人员将 NOLOCK 放在那里,对吧?
  • @p2k 如果您有一个复杂的查询,您可能已经达到 SQL Server 全文搜索可以为您做的最大值。我们遇到了类似的问题,请在此处查看我的问题和链接文章:stackoverflow.com/questions/39661792/… 您可能希望转换为外部搜索引擎(solr、elasticsearch)或重新设计查询以减少搜索条件的数量。
  • @TT。好吧,让我们放弃 NOLOCK ;)。我在OP回复他有多少数据并且最多有35个搜索条件之前就说过了。当然,对于具有如此多搜索条件的多个用户,必须同时遍历超过 3+ 百万条记录的 FTS 索引可能会导致 CPU 和 RAM 使用率过高。 OP 需要转换查询和/或数据库结构,并尝试使用预先计算的夜间报告来完成此类任务。
【解决方案2】:

我想建议启用服务器级别的配置:“优化即席工作负载”

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 2022-07-26
    相关资源
    最近更新 更多