关系型数据库严重依赖底层的硬件资源,CPU是服务器的大脑,当CPU开销很高时,内存和硬盘系统都会产生不必需要的压力。CPU的性能问题,直观来看,就是任务管理器中看到的CPU利用率始终处于100%,而侦测CPU压力的工具,最精确的就是性能监控器。

在SQL Server中,有五类操作非常消耗CPU资源:

  • 编译执行计划,生成执行计划是非常消耗CPU资源的操作,当一个语句生成执行计划之后,SQL Server把其存储在Plan Cache中,以便重用执行计划。
  • 执行排序(Sort),聚合计算(Aggregation),哈希连接操作都需要消耗CPU来完成计算
  • IO指令的执行需要CPU的协助,大量Disk IO会消耗一定的CPU资源来执行;
  • 以并发方式执行查询请求,并发控制受到配置选项 Maximum Degree of Parallelism 和 Cost Threshold of Parallelism的影响;
  • 数据的压缩和解压缩,数据的压缩和解压缩都需要CPU的计算来完成

一,使用性能监控器侦测CPU压力

性能监控器(PerfMon)是侦测CPU压力的首选工具,对于CPU高利用率,在使用性能监控器时可以重点关注下面的3个计数器:

  • Processor/ %Privileged Time:花费在执行Winidows内核命令上的处理器时间的百分比
  • Processor/ %User Time:花费在处理应用程序上的处理器时间的百分比
  • Process(sqlserver.exe)/ % Processor Time:每个处理器所有进程的总处理时间

除了上面这3给计数器之外,还可以使用SQL Statistics计数器来监控:

  • SQL Server:SQL Statistics/Auto-Param Attempts/sec
  • SQL Server:SQL Statistics/Failed Auto-params/sec
  • SQL Server:SQL Statistics/Batch Requests/sec
  • SQL Server:SQL Statistics/SQL Compilations/sec
  • SQL Server:SQL Statistics/SQL Re-Compilations/sec
  • SQL Server:Plan Cache/Cache Hit Ratio

二,使用DMV侦测CPU压力

使用DMV来侦测当前系统CPU的压力,常规的步骤是:

  • step1:使用sys.dm_os_wait_stats 检查等待,查看是否存在CPU压力
  • step2:根据等待类型,通过sys.dm_os_wait_stats 和 sys.dm_os_schedulers 确定CPU问题的种类
  • step3:通过sys.dm_exec_query_stats 和 sys.dm_exec_sql_text 找出计划缓存中CPU消耗最高的查询
  • step4:通过sys.dm_os_waiting_tasks找到当前任务中CPU相关的等待类型中CPU消耗最高的任务
  • step5:从sys.dm_exec_requests中找到当前查询中CPU资源使用最高的查询。

三,CPU相关的等待

从sys.dm_os_wait_stats 中检查等待,对于CPU压力,通常相关的等待类型是:SOS_SCHEDULER_YIELD和CXPACKET

1,CXPACKET

CXPACKET是最常见的并行等待,如果一个查询由多个线程组成,那么只有在最慢的那个线程完成之后,整个查询才会完成。这就是并行查询的木桶效应,一个木桶的容量取决于组成木桶最短的那块木条的长度。

在多CPU的环境中,一个单独的查询可以使用多个线程来共同完成,每个线程单独处理数据集的一部分。在并行处理的过程中,如果某个线程处于落后状态,CXPACKET等待就会产生。但是,应该注意,CXPACKET等待并不总是表示系统存在性能问题。需要测试,合理设置并行度阈值(Cost Threshold for Parallelism,CTP)和最大并发度(Max Degree of Parallelism,MDP),这两个配置项的用途是:

  • CTP是指只有查询的开销超过一定的阈值之后,才会使用并发操作
  • MDP应设置为CPU的内核数量,表示最多使用多少个线程同时处理任务

出现CXPACKET等待的原因是:

  • 在可变类型中,数据的分布存在严重的倾斜,比如某列nvarchar类型的数据,有些数据的长度是几个字符,有些的几千个字符,对这样的数据进行查询时,会导致某些线程执行很快,但另一个线程执行很慢。
  • 查询所需要的数据存放在不同的IO子系统中,而这些子系统的性能又存在差异
  • 查询所需要的数据中,不同部分的碎片不同,所需的IO也不同。IO数量直接影响运行速度和资源开销,从而导致查询过程中不同线程的运行速度不同。

2,SOS_SCHEDULER_YIELD

SOS_SCHEDULER_YIELD是在多任务调度系统中才会出现的等待类型,多任务是指服务器拥有多核,可以同时处理多个任务。SOS_SCHEDULER_YIELD等待类型就发生在一个任务放弃当前占用的资源,让其他任务使用资源以执行下去。

SQL Server以协同模式运行,在必要的时候,SQL Server会让出资源给其他线程,通常来说,这种让步是临时的,但是,当长期、大量出现这种等待的时候,有可能意味着CPU存在压力,这个时候,可以检查 sys.dm_os_schedulers,看看当前有多少个 runnable的任务在运行,

select schedule_id, current_tasks_count, runnable_task_count, work_queue_count, pending_disk_io_count
from sys.dm_os_schedulers
where schedule_id<255

通常情况下,如果 runnable_task_count 字段长时间存在两位数的数值,就意味着CPU可能存在压力,无法应对当前的工作负载。

四,常见的高CPU利用率的原因

下面总结了7个常见的高CPU利用率的情况。

1,缺失索引

当没有合适的索引用于支持查询时,一般只能通过大面积表扫描来获取所需要的信息,这会导致SQL Server需要处理很多非必要的数据,由于需要加载很多非必要的数据到内存,这些IO操作需要消耗CPU资源,大量数据被加载到内存也会引起内存压力,导致计划缓存被移除,使得SQL Server必须重新编译执行计划,编译和生成执行计划也是高CPU开销操作。

2,统计信息过时

SQL Server 优化器借助统计信息来预估查询开销,如果统计信息过时、不准确,会导致优化器产生不合适的执行计划。

可以检查一下图形执行计划,如果预估行数和实际行数的的差异很大,就说明统计信息过时,需要更新。

3,非SARG查询

SARG是 Search Argumeng的缩写,简单来说,如果一个查询条件(where,on)能用到索引查找操作(seek index),那么该表达式就是SARG。

通常情况下,对索引列使用了计算式或函数,或者使用了 like '%str'等都会导致索引失效,这类查询都属于非SARG查询。

4,隐式转换

由于SQL Server无法匹配不同类型的数据,所以需要先把数据转换为相同的类型,才能进行匹配。

如果在实际的执行计划中出现 CONVERT_IMPLICIT 操作符,就说明出现了类型的隐式转换。

5,参数嗅探

参数嗅探是指在创建存储过程,或者参数化查询的执行计划时,根据传入的参数进行预估并生成执行计划。SQL Server生成的执行计划对当前参数来说是最优的,而对其他大多数参数来说,是非常低效的。有些时候,针对一个查询的第一次传参,已经产生了一个执行计划,当后续传参时,由于存在对应参数的数据分布等问题,导致原有的执行计划无法高效地响应查询请求,这就出现参数嗅探问题。

对于参数嗅探问题,可以使用语句重编译,编译提示(optimize for)等功能来避免。

6,非参数Ad-Hoc查询

非参数Ad-Hoc查询,是指SQL Server 缓存了大量的只用一次的计划缓存,造成内存资源和CPU资源的浪费,可以使用存储过程、参数化的Ad-Hoc查询或启用 “Optimize for Ad Hoc Workloads”来避免。

参数化的Ad-Hoc查询通常是指使用 sp_executesql 来执行一段TSQL代码。

“针对即席工作负载进行优化”是一个Server级别的性能优化选项,用于提高包含许多临时批处理的工作负载的计划缓存的效率,如果把该选项设置为True,则数据库引擎在首次编译批处理时只保留计划缓存中的一个存根,而不是存储整个执行计划。当再次调用该批处理时,数据库引擎识别出该批处理在之前被执行过,进而从计划缓存中删除该执行计划的存根,并把完全编译的执行计划添加到计划缓存中。当非参数化的Ad-Hoc查询较多时,可以避免计划缓存存储过多的不会被复用的执行计划。

7,压缩操作

压缩和解压缩都是CPU高开销的操作,数据压缩、备份压缩和日志流压缩通过增加CPU的利用率来降低IO子系统压力和硬盘空间压力。数据压缩的优点是降低IO子系统的压力,提高查询的性能,其缺点是消耗CPU资源,对数据的插入和更新操作有负面影响。

参考文档:

性能调优2:CPU的更多相关文章

  1. sql server 性能调优之 CPU消耗最大资源分析1 (自sqlserver服务启动以后)

    一. 概述 上次在介绍性能调优中讲到了I/O的开销查看及维护,这次介绍CPU的开销及维护, 在调优方面是可以从多个维度去发现问题如I/O,CPU,  内存,锁等,不管从哪个维度去解决,都能达到调优的效 ...

  2. (转)SQL Server 性能调优(cpu)

    摘自:http://www.cnblogs.com/Amaranthus/archive/2012/03/07/2383551.html 研究cpu压力工具 perfom SQL跟踪 性能视图 cpu ...

  3. [转]SQL Server 性能调优(cpu)

      研究cpu压力工具 perfom SQL跟踪 性能视图 cpu相关的wait event Signal wait time SOS_SCHEDULER_YIELD等待 CXPACKET等待 CME ...

  4. 【总结】性能调优:JVM内存调优相关文章

    [总结]性能调优:JVM内存诊断工具 [总结]性能调优:CPU消耗分析 [总结]性能调优:消耗分析 JVM性能调优

  5. 【目录】sql server 性能调优

    随笔分类 - sql server 性能调优 sql server 性能调优之 资源等待之网络I/O 摘要: 一.概述 与网络I/O相关的等待的主要是ASYNC_NETWORK_IO,是指当sql s ...

  6. 艾编程coding老师:深入JVM底层原理与性能调优

    1. Java内存模型JMM,内存泄漏及解决方法:2. JVM内存划分:New.Tenured.Perm:3. 垃圾回收算法:Serial算法.并行算法.并发算法:4. JVM性能调优,CPU负载不足 ...

  7. 性能调优案例分享:Mysql的cpu过高

    性能调优案例分享:Mysql的cpu过高   问题:一个系统,Mysql数据库,数据量变大之后.mysql的cpu占用率很高,一个测试端访问服务器时mysql的cpu占用率为15% ,6个测试端连服务 ...

  8. CPU开销sql server 性能调优

    sql server 性能调优 CPU开销分析 一. 概述 上次在介绍性能调优中讲到了I/O的开销查看及维护,这次介绍CPU的开销及维护, 在调优方面是可以从多个维度去发现问题如I/O,CPU, 内存 ...

  9. 鲲鹏性能优化十板斧(二)——CPU与内存子系统性能调优

    1.1 CPU与内存子系统性能调优简介 调优思路 性能优化的思路如下: l   如果CPU的利用率不高,说明资源没有充分利用,可以通过工具(如strace)查看应用程序阻塞在哪里,一般为磁盘,网络或应 ...

  10. hadoop 性能调优与运维

    hadoop 性能调优与运维 . 硬件选择 . 操作系统调优与jvm调优 . hadoop运维 硬件选择 1) hadoop运行环境 2)  原则一: 主节点可靠性要好于从节点 原则二:多路多核,高频 ...

随机推荐

  1. Android--底部导航栏的动态替换方案

    1.通常来说,一般情况下,我们的app的BottomTab会有集中实现方式. 自定义view,然后自己写逻辑去实现互斥. 自由度最高,因为啥都是自己写的. 使用RadioGroup+RadioButt ...

  2. git 入门教程之回到过去

    回到过去 背景 现在你已经掌握git的基本操作了,文件发生更改首先使用 git add 添加更改,然后 git commit 提交全部更改,当本地文件再次发生更改时,仍然需要git add 和 git ...

  3. SQL中触发器的使用

    创建触发器 是特殊的存储过程,自动执行,一般不要有返回值 类型: 1.后触发器 (AFTER,FOR)先执行对应语句,后执行触发器中的语句 2.前触发器  并没有真正的执行触发语句(insert,up ...

  4. java导出数据到excel里:直接导出和导出数据库数据

    一.直接导出 package com.ij34.util; import java.io.FileNotFoundException; import java.io.FileOutputStream; ...

  5. Foreach用法

    循环语句是编程的基本语句,在C#中除了沿用C语言的循环语句外,还提供了foreach语句来实现循环.那么我要说的就是,在循环操作中尽量使用foreach语句来实现.   为了来更好地说明为什么要提倡使 ...

  6. c/c++ 线性表之双向链表

    c/c++ 线性表之双向链表 线性表之双向链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,每个节点的before都指向前一个节点,最后一个节点的下一个节点是NULL. 真实 ...

  7. C++多线程同步技巧(一) --- 临界区

    简介 C++中关于多线程的内容对于构建工程来说是至关重要的,C++本身也对关于多线程的操作提供了很好的支持.本章笔者就来介绍一下C++有关于多线程的重要知识点---临界区. 临界区的作用 线程就像是进 ...

  8. shell 获取时间

    获取当前时间 t=$(date +"%Y-%m-%d %H-%M-%S") echo $t 获取前一天的当前时间 time=$(date -d "-1 day" ...

  9. python 基础操作--数据类型

    一.变量 1.定义:将运算的中间结果暂存到内存,以便后续程序调用. 2.命名规则 1.变量由字母.数字.下划线搭配组合而成: 2.不可以用数字开头,也不能全都是数字: 3.不能是python 关键字, ...

  10. MySQL高级知识(四)——Explain

    前言:explain(执行计划),使用explain关键字可以模拟优化器执行sql查询语句,从而知道MySQL是如何处理sql语句.explain主要用于分析查询语句或表结构的性能瓶颈. 注:本系列随 ...