一.背景

1.1 问题描述

近期发现一台SQL Server的CPU利用率很不稳定,发现不定时的飙升到100%,更可怕的是在业务繁忙时,影响了业务调用,失败率明显增加,所以,减低CPU的利用率,是迫切需要解决的问题。

CPU升高的原因直观上来说,就是CPU(中央处理器)的负载过高, 中央处理器忙不过来。进一步分析的话,可以从两个角度优化,1.减少单个CPU 的处理时间;2.减少单个任务占有的CPU核数,即一个任务不要分配太多的CPU核数。

1.2 优化的方法

1.表结构的优化,例如索引是否合理、关联表字段的定义是否一致等;

2.SQL 语句的优化;

3.表数据量是否归档、缩减;

4.将数据缓存到缓存层(如,Reids),减少对DB的访问;

5.DB实例配置是否需要优化;

6.升级硬件。

二. 问题处理过程

 2.1 优化前

从这个监控图可以看出,CPU最大值为100%,平均值为19%,毛刺比较明显。

2.2 定位SQL语句

通过常用的SP,很快定位到了SQL语句,是关于一张表的查询,语句简单,但是表的数据量比较大(7600W),查询出的数据有(4000W)。这张表每天的写入量<100W。

并且和研发确认,此SQL的调用也是周期性的,比如5分钟查询一次,基本符合Zabbix周期性CPU毛刺突起。

2.3 处理步骤

Step 1 .考虑到,CPU突然飙升,毛刺陡然加剧,冲刺到100%,并且问题SQL 不是最近新上线,所以,我们的第一反映是 索引走偏,统计信息失效了。但是 刷新了 表统计信息 ,情况没有好转。

Step 2. 考虑到是不是索引失效了,我们坚持到业务低峰期,重建了表的索引,情况 依然没有好转。

Step 3.考虑是不是表的数据量到了一定规模,才导致的此问题,和业务研发确认后,将历史数据归档,归档了2800W,数据量由7600W减少到4800W。数据量减少后,情况有所好转,SQL事务的排队和阻塞 明显减少。但是毛刺突起依然明显,CPU 100% 依然存在。

..........

无语

.........

Step 4 这时想到,最大并行度 。当SQL Server 发现一条指令比较复杂(不仅仅是SQL语句复杂,查询的数据量比较大也是复杂),会决定用多少个线程并行执行,从而提高整体相应时间。如果指令复杂,甚至需要所有CPU来运行这些线程,别的用户发过来的指令会受到影响,甚至可能拿不到CPU执行。即需要调整max degree of parallelism的值

查看问题实例 发现没有设置,即可以使用所有的CPU。修改参数,将最大并行度将至4.执行以下命令:

exec sp_configure 'max degree of parallelism',4
go
RECONFIGURE
GO

此时 毛刺消失了,问题解决了。

2.4 优化后

优化后,从监控图中可以看出,CPU的最大值降至了25%,平局值为7%。

三.定位问题SQL常用的SP

当我们遇到DB性能问题或DBServer监控指标异常时,以下四个SP,可以帮忙我们快速定位SQL语句。

3.1 查看当前阻塞排队的情况

/*
---------------------------------------------------------------------------------
uspm_Block
功能:查看阻塞和锁,阻塞源头
参数:无
---------------------------------------------------------------------------------
*/
create PROCEDURE [dbo].[uspm_Block]
as --查找有关被阻塞的请求的信息(含用户)
SELECT s.loginame
,[Individual Query] = SUBSTRING (qr.text,qs.statement_start_offset/2,
(CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qr.text)) * 2
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2)
,qs.session_id ,s.counts AS [进程个数],qs.status ,qs.blocking_session_id
,qs.wait_type ,qs.wait_time ,qs.wait_resource
,qs.transaction_id
FROM SYS.DM_EXEC_REQUESTS qs (nolock)
LEFT JOIN (
SELECT spid,MAX(loginame)AS loginame,COUNT(0)AS counts FROM SYS.SYSPROCESSES (nolock) GROUP BY spid
) s ON qs.session_id=s.spid
OUTER APPLY SYS.DM_EXEC_SQL_TEXT(qs.sql_handle) AS qr
WHERE qs.status = N'suspended'
--and s.loginame<>''
ORDER BY qs.wait_time DESC --查找阻塞源头v3.0
SELECT SP.spid
,CASE WHEN ST1.text IS NULL THEN ST2.text
ELSE SUBSTRING (ST1.text,SR.statement_start_offset/2,
(
CASE WHEN SR.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), ST1.text)) * 2
ELSE SR.statement_end_offset
END - SR.statement_start_offset)/2
)
END AS [T-sql]
,SP.loginame
,DB_NAME(SP.dbid) AS [db_name]
,SP.open_tran,SP.hostname,SP.program_name,SP.waitresource,SP.*
FROM SYS.SYSPROCESSES SP (nolock)
LEFT JOIN SYS.DM_EXEC_REQUESTS SR (nolock) ON SP.spid=SR.session_id
LEFT JOIN SYS.DM_EXEC_CONNECTIONS SC (nolock) ON SP.spid=SC.session_id
OUTER APPLY SYS.DM_EXEC_SQL_TEXT(SC.most_recent_sql_handle) AS ST2
OUTER APPLY SYS.DM_EXEC_SQL_TEXT(SR.sql_handle) AS ST1
WHERE SP.spid IN
(
SELECT BLOCKED FROM SYS.SYSPROCESSES (nolock) WHERE BLOCKED<>0
)
AND SP.BLOCKED=0
GO

3.2 查看 当前最消耗CPU的SQL

/*
---------------------------------------------------------------------------------
uspm_perf_topcpu
功能:取当前N个最耗CPU的SQL
参数:@topCount --N的具体数量,默认取前20条
示例:
1.取前10条
exec uspm_perf_topcpu 2.取前20条最耗CPU的SQL
exec uspm_perf_topcpu @topCount=20
---------------------------------------------------------------------------------
*/
CREATE PROCEDURE [dbo].[uspm_perf_topcpu]
(@topCount int=10)
as
set nocount on
declare @cmd varchar(1000)
select @cmd='
SELECT TOP '+ CAST(@topCount AS VARCHAR)+' SUBSTRING(text, (statement_start_offset/2) + 1,
((CASE statement_end_offset
WHEN -1 THEN DATALENGTH(text)
ELSE statement_end_offset
END - statement_start_offset)/2) + 1
) AS query_text
,b.hostname
,b.loginame
,a.*
,qr.text
,qt.query_plan
FROM sys.dm_exec_requests a (nolock)
INNER JOIN sys.sysprocesses b (nolock) on a.session_id=b.spid
CROSS APPLY sys.dm_exec_sql_text(a.sql_handle) as qr
CROSS APPLY sys.dm_exec_query_plan(a.plan_handle)as qt
ORDER BY a.total_elapsed_time DESC' exec(@cmd) GO

3.3 查看执行时间最长的SQL

/*
---------------------------------------------------------------------------------
uspm_perf_topduration
功能:取N个执行时间最长的SQL
参数:@topCount --N的具体数量,默认取前50条
示例:
--1.取前50条
exec uspm_perf_topduration --2.取前10条执行时间最长的SQL
exec uspm_perf_topduration @topCount=10
---------------------------------------------------------------------------------
*/
CREATE PROCEDURE [dbo].[uspm_perf_topduration]
(@topCount int=50)
as
set nocount on
declare @cmd varchar(600)
select @cmd='
select
highest_cpu_queries.plan_handle,
highest_cpu_queries.total_worker_time,
q.dbid,
q.objectid,
q.number,
q.encrypted,
q.[text]
from
(select top '+ cast(@topCount as varchar)+'
qs.plan_handle,
qs.total_worker_time
from
sys.dm_exec_query_stats qs (nolock)
order by qs.total_worker_time desc) as highest_cpu_queries
cross apply sys.dm_exec_sql_text(plan_handle) as q
order by highest_cpu_queries.total_worker_time desc'
exec(@cmd)
GO

3.4 当前SQL执行概览

/*
---------------------------------------------------------------------------------
uspm_perf_cpudetail
功能:查看CPU的任务数量,使用率,CPU瓶颈
参数:无参
---------------------------------------------------------------------------------
*/
CREATE PROCEDURE [dbo].[uspm_perf_cpudetail]
as
set nocount on
--1.Cpu_Task
SELECT '查看cpu任务'
SELECT scheduler_id, current_tasks_count, runnable_tasks_count
FROM sys.dm_os_schedulers (nolock)
WHERE scheduler_id < 255 ---2.CUP_USING
SELECT '查看cpu使用情况'
declare @ts_now bigint
--select @ts_now = cpu_ticks / convert(float, cpu_ticks_in_ms) from sys.dm_os_sys_info (nolock)
select @ts_now = cpu_ticks/(cpu_ticks/ms_ticks) from sys.dm_os_sys_info (nolock) select top 50 record_id,
dateadd(ms, -1 * (@ts_now - [timestamp]), GetDate()) as EventTime,
SQLProcessUtilization as [CPU使用率,不能始终处于高位],
SystemIdle,
100 - SystemIdle - SQLProcessUtilization as OtherProcessUtilization
from (
select
record.value('(./Record/@id)[1]', 'int') as record_id,
record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') as SystemIdle,
record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') as SQLProcessUtilization,
timestamp
from (
select timestamp, convert(xml, record) as record
from sys.dm_os_ring_buffers (nolock)
where ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR'
and record like '%<SystemHealth>%') as x
) as y
order by record_id desc --3.CPU_NECK
SELECT '查看CPU瓶颈'
select cast([signal_wait_time_ms] as decimal(30,2))/[wait_time_ms] as [百分比] ,*
from sys.dm_os_wait_stats (nolock)
where [wait_time_ms]<>0
and cast([signal_wait_time_ms] as decimal(30,2))>([wait_time_ms]*0.25 )
order by 1 desc SELECT '查看百分比是否>10%,如果大于10%,考虑降低并行度'
select cast([signal_wait_time_ms] as decimal(30,2))/[wait_time_ms] as [百分比],*
from sys.dm_os_wait_stats (nolock)
where [wait_time_ms]<>0 AND wait_type='CXPACKET'
GO

SQL Server CPU 利用率毛刺的分析定位与解决的更多相关文章

  1. CPU利用率异常的分析思路和方法交流探讨

    CPU利用率异常的分析思路和方法交流探讨在生产运行当中,经常会遇到CPU利用率异常或者不符合预期的情况,此时,往往暗示着系统性能问题.那么究竟是核心应用的问题?是监控工具的问题?还是系统.硬件.网络层 ...

  2. SQL Server Cpu 100% 的常见原因及优化

    SQL Server Cpu 100% 的情况并不太常见,一般引起 SQL Server 产生性能问题的,都是 阻塞.连接数.IO 磁盘等.所以,一般SQL Server 的使用率都是比较低的.但是, ...

  3. Sql Server CPU 性能排查及优化的相关 Sql

    Sql Server CPU 性能排查及优化的相关 Sql 语句,非常好的SQL语句,记录于此: --Begin Cpu 分析优化的相关 Sql --使用DMV来分析SQL Server启动以来累计使 ...

  4. windows系统与SQL SERVER 2008数据库服务性能监控分析简要

    软件系统性能测试体系流程介绍之windows系统与SQL SERVER 2008数据库服务性能监控分析简要 目前大部分测试人员对操作系统资源.中间件.数据库等性能监控分析都是各自分析各自的监控指标方式 ...

  5. sql server 2012提示:评估期已过 的解决办法 附序列号

    sql server 2012提示评估期已过的解决方法: 第一步:进入SQL2012配置工具中的安装中心. 第二步:再进入左侧维护选项界面,然后选择选择版本升级. 第三步:进入输入产品密钥界面,输入相 ...

  6. SQL Server 2008 R2评估期已过的解决办法

    SQL Server 2008 R2评估期已过的解决办法   发现问题 北美产品测试服每日随机任务没有刷新 每日随机任务是使用数据库作业定期执行操作,重置玩家随机任务项 排查问题  www.2cto. ...

  7. sql server 2012提示评估期已过的解决办法 附序列号

    sql server 2012提示评估期已过的解决方法: 第一步:进入SQL2012配置工具中的安装中心. 第二步:再进入左侧维护选项界面,然后选择选择版本升级. 第三步:进入输入产品密钥界面,输入相 ...

  8. 用户 'sa' 登录失败。该用户与可信 SQL Server 连接无关联'。错误代码:18452 解决办法

    原文:https://blog.csdn.net/wuxianwei/article/details/6330270 SQLSERVER 2005采用'SQLSERVER身份验证'去登录, 出错的原因 ...

  9. SQL SERVER——CPU问题定位与解决

        CPU问题定位基本流程: 性能计数器诊断 主要用到的性能计数器 %Process Time 全实例 (主要用于查看当前服务器的CPU 情况) %Process Time sqlservr (主 ...

随机推荐

  1. [Linux]经典面试题 - 系统管理 - 备份策略

    [Linux]经典面试题 - 系统管理 - 备份策略 目录 [Linux]经典面试题 - 系统管理 - 备份策略 一.备份目录 1.1 系统目录 1.2 服务目录 二.备份策略 2.1 完整备份 2. ...

  2. .NET Worker Service 部署到 Linux 作为 Systemd Service 运行

    上一篇文章我们了解了如何将.NET Worker Service 作为 Windows 服务运行,今天我接着介绍一下如何将 Worker Service 部署到 Linux 上,并作为 Systemd ...

  3. Unity中的.Meta文件

    .meta文件是用于辅助管理Unity资源文件的文件,删除后,Unity会自动生成,里面记录了各个资源Inspector的信息,属性等等,Unity是不会改变源资源文件的,没有意义,它是靠.meta文 ...

  4. Linux-NFS存储

    1.什么是NFS NFS是Network File System 的缩写,中文意思是网络文件共享系统,它的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以共享文件或目录. 2.NFS存储服务 ...

  5. 11 监控MySQL主从状态是否异常

    #!/bin/bash source /etc/profile # 主从同步 # master:binlog # slave:relaylog # 写->master->binlog< ...

  6. uniapp uni.navigateTo 传值传对象

    uni.navigateTo({ url: '/pages/details?obj='+ encodeURIComponent(JSON.stringify(item)) }); 接收: onLoad ...

  7. JUnit5的Tag、Filter、Order、Lifecycle

    Tag JUnit5可以使用@Tag注解给测试类和测试方法打tag,这些tag能用来在执行时进行过滤,它跟group有点类似. tag应该遵循以下规则: 不能为null或者为空. 不能包含空格. 不能 ...

  8. bugku crypto wp上半部分汇总

    1.滴答~滴 摩斯码,在线解开. 2. 栅栏密码,在线解就出flag了. 3. Ook解密,由.?!Ook组成密文,在线网站解密 4.这不是摩斯密码 有点像jsfuck,发现又不是,因为不会出现大于号 ...

  9. Linux | 搜索命令

    grep grep 命令用于在文本中执行关键词搜索,并显示匹配的结果,格式:grep[选项][文本] grep命令的参数及其作用 参数 作用 -b 将可执行文件当作文本文件对待 -c 公显示找到的行数 ...

  10. [NOI2000] 古城之谜

    题目描述 给定 n 和 n 个信息,每个信息包含一个词性 a (只有三种:名,动,辅)和对应的词 mot ,形为" \(a.mot\) ".(一次可能多词性) 最后给一个长度不大于 ...