SQL Server上的CPU使用率高-查询速度慢


11

我们的MS SQL Server使用了大约95%的CPU能力。

重新启动服务器(硬件)或重新启动SQL-Service后,使用率为0%,并且在1-3天的过程中缓慢增加。取决于使用了多少。

当超过80%时,每个查询都会非常慢。

我们的网站正在处理大量重大查询,因此其中一些需要45-60秒。重新启动后(CPU使用率低于80%),相同的查询需要11到20秒的时间。


我怎样才能解决这个问题?我已经在线阅读了亲和力掩码可以调整CPU使用率的信息,但亲和力设置已禁用。我不能改变他们。这是因为我只有1个处理器吗?

与查询本身有关的技巧很多,但我们的网站和服务相当庞大,而且变化太多。

它们中的大多数已经非常优化。


即使只花了2秒钟,我也无法继续重启SQL服务,因为我们有一个警报服务,允许人们拨入并记录一条消息,然后将呼叫选定的组并听到记录的消息。

数百个Search and Rescue团队都使用此系统,如果SQL-Service在警报期间重新启动,它将终止,并且不会通知调用它的人员。


我搜索了整个地方,但是除了“亲和力面具”以外,什么都找不到,我无法更改。

必须有一种在不终止当前查询的情况下清除CPU缓存的方法...对吗?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB

评论不作进一步讨论;此对话已转移至聊天
保罗怀特9

Answers:


7

这是一个很长的路,但是您可能想看看您的强制参数设置。如果在性能不佳时看到大量查询计划,则查询将不会按照您期望的方式进行缓存,并且查询将花费很长时间浏览整个缓存以查看是否有已在使用的计划。如果清除缓存可以解决此问题,则可能需要研究更改强制参数化设置。您可以使用以下方法清除缓存:

DBCC FREEPROCCACHE

如果清除由以下人员处理的缓存,则可以查看强制参数化设置是什么:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

可能设置为默认值0。如果他们愿意,可以通过执行以下操作将其设置为true:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

应该首先在开发环境中完成此操作,然后查看这是否会对数据库产生其他负面影响。可以使用以下方法还原它:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;

5
请注意,释放过程高速缓存实际上可能会导致CPU的大幅增加-因为所有查询现在都必须重新编译其执行计划。
亚伦·伯特兰

18

Affinity不会“调整CPU使用率”(例如,使您的CPU执行更少的工作),它允许您关闭CPU(可能使其可用于同一台计算机上的另一个实例)或将CPU设置为仅与I / O一起使用。即使您有多个CPU,您也将无法使用前者来帮助您实现目标,而我们也不可能猜测后者,因为我们不知道是什么导致您的CPU使用率如此之高。可能是由于索引性能极差,过度编译,标量UDF数量过多,I / O抖动导致的,谁知道呢?(I / O可能是原因,如果数据库大于3 GB左右,它将不断地需要在缓冲池内存中交换数据,这会给CPU造成很大的损失。)

同样,CPU高速缓存是您无需担心的麻烦。我非常怀疑您的CPU是否由于CPU缓存问题而无法正常运行95%。

为了帮助缩小CPU压力的来源,并假设您正在使用存储过程,可以查看Glenn Berry的诊断查询(从此处获取)-确保在正确的数据库上下文中运行它:

-- Top Cached SPs By Total Worker time (SQL Server 2012). 
-- Worker time relates to CPU cost  (Query 44) (SP Worker Time)

SELECT TOP (25) 
  p.name AS [SP Name], 
  qs.total_worker_time AS [TotalWorkerTime], 
  qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], 
  qs.execution_count, 
  ISNULL(qs.execution_count/DATEDIFF(Second, qs.cached_time, GETDATE()), 0) 
    AS [Calls/Second],
  qs.total_elapsed_time, 
  qs.total_elapsed_time/qs.execution_count AS [avg_elapsed_time], 
  qs.cached_time
FROM sys.procedures AS p WITH (NOLOCK)
INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (NOLOCK)
ON p.[object_id] = qs.[object_id]
WHERE qs.database_id = DB_ID()
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

-- This helps you find the most expensive cached stored procedures from a CPU perspective
-- You should look at this if you see signs of CPU pressure

如果您不使用存储过程,那么John Samson的以下示例可以帮助隔离临时查询(来自此处):

SELECT TOP (25)
    qs.sql_handle,
    qs.execution_count,
    qs.total_worker_time AS Total_CPU,
    total_CPU_inSeconds = --Converted from microseconds
    qs.total_worker_time/1000000,
    average_CPU_inSeconds = --Converted from microseconds
    (qs.total_worker_time/1000000) / qs.execution_count,
    qs.total_elapsed_time,
    total_elapsed_time_inSeconds = --Converted from microseconds
    qs.total_elapsed_time/1000000,
    st.text,
    qp.query_plan
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 qs.total_worker_time DESC OPTION (RECOMPILE);

您还可以查看Adam Machanic的sp_WhoIsActive,这是一个存储过程,可以快速分析所有当前正在运行的查询,并允许您按需要对其进行排序(例如,根据您的情况@sort_order = '[CPU] DESC')。

不过,我要做的第一件事是-购买更好的硬件-特别是如果这对于搜索和救援团队而言确实至关重要的话。您应该有更多的CPU和更多的RAM以服务您的应用程序。您还绝对需要更好的高可用性(例如,群集,镜像或可用性组)。没有理由重启物理计算机会使您的应用程序完全脱机-我们为该问题提供了更好的解决方案。最后,我假设此“服务器”只有一个棘手的磁盘驱动器。这意味着来自操作系统,SQL Server数据文件,日志文件,tempdb等的所有I / O都将通过单个控制器并共享单个驱动器上的读/写活动。获取更多磁盘。如果可能的话/在可能的地方获得SSD。使用RAID并尝试尽可能多地扩展I / O。

综上所述,将硬件扔到问题上将不是修复的唯一部分。无论您使用的是哪种硬件,都需要准确地找出导致CPU使用率过高的原因,然后解决这些问题。

另请参阅此StackOverflow问题以了解其他一些想法:

/programming/945063/how-do-i-find-out-what-is-hammering-my-sql-server


0

以下建议是“黑暗中的尝试”,因为我看不到实际的代码。

首先是SP可能正在打开游标并使它们保持打开状态。阅读有关游标的信息,尤其是关闭和取消分配。可能有人正在关闭,但没有取消分配游标。由于升级,行为可能已更改,2012年可能会将剩余游标与2008 R2区别对待。

其次是可能存在未清除的表锁。同样,我距离很远,所以我无法分辨,但这表明有人在“开始事务”之后创建了一个全局临时表,并且要么不执行“结束事务”,要么存储过程无法完成锁定tempdb中的表占用空间。

您是否正在使用WinLink?听起来有些熟悉。


-4

您应该有一个像memcached这样的缓存机制来提高性能


但这不会改变SQL Server上的CPU使用率,对吗?这只会使查询在网站上的运行速度更快,并且可能会出现问题,即某个表中的某内容已更改,而其他人正在使用同一表中的内存缓存结果,对吗?
Levi Johansen

@Levi如果将查询结果缓存在中间层的某个位置,则查询不会访问数据库(除非您需要刷新缓存)。
亚伦·伯特兰

1
如果没有人在网站上时CPU的容量也很高,那么显然缓存Web级内容将无济于事。Memcached是一个很棒的工具,但是它不能代替有能力的人坐下来找出服务器在做什么,而服务器本来应该什么也不做。
TomTom 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.