SQL Server CPU 利用率毛刺的分析定位与解决
一.背景
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 利用率毛刺的分析定位与解决的更多相关文章
- CPU利用率异常的分析思路和方法交流探讨
CPU利用率异常的分析思路和方法交流探讨在生产运行当中,经常会遇到CPU利用率异常或者不符合预期的情况,此时,往往暗示着系统性能问题.那么究竟是核心应用的问题?是监控工具的问题?还是系统.硬件.网络层 ...
- SQL Server Cpu 100% 的常见原因及优化
SQL Server Cpu 100% 的情况并不太常见,一般引起 SQL Server 产生性能问题的,都是 阻塞.连接数.IO 磁盘等.所以,一般SQL Server 的使用率都是比较低的.但是, ...
- Sql Server CPU 性能排查及优化的相关 Sql
Sql Server CPU 性能排查及优化的相关 Sql 语句,非常好的SQL语句,记录于此: --Begin Cpu 分析优化的相关 Sql --使用DMV来分析SQL Server启动以来累计使 ...
- windows系统与SQL SERVER 2008数据库服务性能监控分析简要
软件系统性能测试体系流程介绍之windows系统与SQL SERVER 2008数据库服务性能监控分析简要 目前大部分测试人员对操作系统资源.中间件.数据库等性能监控分析都是各自分析各自的监控指标方式 ...
- sql server 2012提示:评估期已过 的解决办法 附序列号
sql server 2012提示评估期已过的解决方法: 第一步:进入SQL2012配置工具中的安装中心. 第二步:再进入左侧维护选项界面,然后选择选择版本升级. 第三步:进入输入产品密钥界面,输入相 ...
- SQL Server 2008 R2评估期已过的解决办法
SQL Server 2008 R2评估期已过的解决办法 发现问题 北美产品测试服每日随机任务没有刷新 每日随机任务是使用数据库作业定期执行操作,重置玩家随机任务项 排查问题 www.2cto. ...
- sql server 2012提示评估期已过的解决办法 附序列号
sql server 2012提示评估期已过的解决方法: 第一步:进入SQL2012配置工具中的安装中心. 第二步:再进入左侧维护选项界面,然后选择选择版本升级. 第三步:进入输入产品密钥界面,输入相 ...
- 用户 'sa' 登录失败。该用户与可信 SQL Server 连接无关联'。错误代码:18452 解决办法
原文:https://blog.csdn.net/wuxianwei/article/details/6330270 SQLSERVER 2005采用'SQLSERVER身份验证'去登录, 出错的原因 ...
- SQL SERVER——CPU问题定位与解决
CPU问题定位基本流程: 性能计数器诊断 主要用到的性能计数器 %Process Time 全实例 (主要用于查看当前服务器的CPU 情况) %Process Time sqlservr (主 ...
随机推荐
- 『心善渊』Selenium3.0基础 — 2、Selenium测试框架环境搭建(Windows)
目录 1.浏览器安装 2.浏览器驱动下载 (1)ChromeDriver for Chrome (2)Geckodriver for Firefox (3)IEDriverServer for IE ...
- 如何基于MindSpore实现万亿级参数模型算法?
摘要:近来,增大模型规模成为了提升模型性能的主要手段.特别是NLP领域的自监督预训练语言模型,规模越来越大,从GPT3的1750亿参数,到Switch Transformer的16000亿参数,又是一 ...
- Telnet查看端口是否通
1. 查看端口是否通畅 telnet IP 端口号 如:telnet 10.150.159.71 5516 2.查看本机是否开启某个端口:netstat -an |findstr "端口 ...
- 如何设置Python环境变量
大家好,我是Yivies.相信很多python的初学者们在进行一顿下一步下一步的安装之后,在windows command命令行输入python的时候会出现这样的情况: 可我们希望它是这样子的: 其实 ...
- react 工程目录简介
创建一个 todolist 项目,下图是其工程目录. node_modules文件夹 里面存放的是我们所建项目放所依赖的第三方的包 public文件夹 favicon.ico 图标文件,网页标题左上角 ...
- Kubernetes之Ingress
在Service篇里面介绍了像集群外部的客户端公开服务的两种方法,还有另一种方法---创建Ingress资源. 定义Ingress (名词)-进入或进入的行为;进入的权利;进入的手段或地点;入口. 接 ...
- 基于C#的socket编程的TCP同步实现
该博客源著地址https://www.cnblogs.com/sunev/archive/2012/08/05/2604189.html 一.摘要 总结一下基于C#的TCP传输协议的涉及到的常用方法及 ...
- 深入学习Netty(2)——传统NIO编程
前言 学习Netty编程,避免不了从了解Java 的NIO编程开始,这样才能通过比较让我们对Netty有更深的了解,才能知道Netty大大的好处.传统的NIO编程code起来比较麻烦,甚至有遗留Bug ...
- uniapp uni.navigateTo 传值传对象
uni.navigateTo({ url: '/pages/details?obj='+ encodeURIComponent(JSON.stringify(item)) }); 接收: onLoad ...
- external-attacher源码分析(2)-核心处理逻辑分析
kubernetes ceph-csi分析目录导航 基于tag v2.1.1 https://github.com/kubernetes-csi/external-attacher/releases/ ...