一文教会你数据库性能调优(附某大型医院真实案例)

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: 原文:一文教会你数据库性能调优(附某大型医院真实案例)前言  微软工程师的一个工程师曾经对性能调优有一个非常形象的比喻:剥洋葱 。我也非常认可,让我们来一层一层拨开外面它神秘的面纱。     六大因素 下面祭出的是我们在给客户分析数据库性能问题最常用的图。
原文: 一文教会你数据库性能调优(附某大型医院真实案例)

前言

 微软工程师的一个工程师曾经对性能调优有一个非常形象的比喻:剥洋葱 。我也非常认可,让我们来一层一层拨开外面它神秘的面纱。

 

 

六大因素

下面祭出的是我们在给客户分析数据库性能问题最常用的图。

看完这个图,你是不是对性能调优有了个基本的概念了.通常来讲我们会依照下面的顺序来进行分析:

硬件能力

系统规模

数据库内部因素

软件环境

这4个的顺序可以有所调整或者交换,但是对于系统的性能优化一定要从全局出发切勿一来就深入到某一个SQL语句的优化,因为可能你花费大量的

时间吧一个SQL从20s 优化到1s,但是整个系统的卡慢仍然存在。

最后才是

业务模型及架构

代码设计

 

实战案例

 

不废话了,开整开整,直接上干货。

时间:2018年1月某天

事件:某医院客户 下午4点 突然出现大面积的卡慢。整个系统出现严重问题,信息中心电话打爆,医院工程师手足无措。

万幸的是我们给数据库装了‘摄像头’,下面就从监控录像来看看发送了什么。然后加以解决

 

硬件能力

CPU

在问题发生时间段内CPU使用率在20%以下,正常。

 

Memory

从下面的图像显示,内存使用正常。

页生命周期

 

 可用内存

 

 

IO

 IO队列平均值很低,15.48 左右有个瞬时的高点,可留意这段时间有没有批量的写入。

总的来看,硬件资源是足够的。

系统规模

问题发生时,每秒的批请求书并不是一个上升趋势,反而有所下降。这是因为系统的拥堵,等待 ,影响了系统的吞吐量。

 数据库内部因素

等待

慢语句

从会话和慢语句的趋势图可以看到,问题发生的时间和客户描述完全吻合,我们可以断定本身事故的确是慢在数据库。

什么导致的慢

检查者个时间段运行中的语句,可以发现下午15.58左右,数据库中开始出现越来越多的CMEMTHREAD等待。

 

 

一直到1900页16.08分的时候,出现了最高达100个并发同时出现CMEMTHREAD等待

什么是CMEMTHREAD等待

微软官方的描述:在任务正在等待线程安全的内存对象时发生。 当多个任务尝试从同一个内存对象分配内存导致争用时,等待时间可能会增加。

这个描述很晦涩,感觉还是完全不知道等待类型是怎么回事,应该怎么处理这类问题。

 

实际上,从官方描述来看是内存争用的问题,但是实际上这个问题的关键在于多个任务的争用,实际上是并发的执行的问题。

场景

  1. 出现在数据库编译或重编译时,将即席执行计划ad hoc plans 插入到计划缓存中的时候
  2.  NUMA架构下,内存对象是按照节点来分区的

内存对象有三种类型的(Global,Per Numa Node,Per CPU)。 SQL Server将允许对内存对象进行分段,以便只有同一节点或cpu上的线程具有相同的底层CMemObj,从而减少来自其他节点或cpu的线程交互,从而提高性能和可伸缩性。减少内存的并发争用

SELECT
type, pages_in_bytes,
CASE
WHEN (0x20 = creation_options & 0x20) THEN 'Global PMO. Cannot be partitioned by CPU/NUMA Node. TF 8048 not applicable.'
WHEN (0x40 = creation_options & 0x40) THEN 'Partitioned by CPU.TF 8048 not applicable.'
WHEN (0x80 = creation_options & 0x80) THEN 'Partitioned by Node. Use TF 8048 to further partition by CPU'
ELSE 'UNKNOWN'
END
from sys.dm_os_memory_objects
order by pages_in_bytes desc

如果你发现,Partitioned by Node 的内存开销是排在前面的,可以使用TRACE FLAG 8048来减少CMEMTHREAD等待.

 

 

从图中可以看到,客户的 Partitioned by Node 是比较靠后的,排在14位。

       3. 补丁

这类场景是最常见的。如果在系统中发现出现大量的CMEMTHREAD等待,优先考虑数据库是不是已经安装最新的补丁

 

2008 r2: FIX: SQL Server 2008 R2 performs poorly when most threads wait for the CMEMTHREAD wait type if the threads use table variables or temp tables to load or update rowsets

2012 ,2014  当您执行许多特殊查询在 SQL Server 2012年或 SQL Server 2014 CMEMTHREAD 等待

 软硬件环境

目前数据库的版本是 11.0.5556.0   而前面提到的补丁,安装后的版本是:11.0.5623.0 

 

代码设计

是什么语句产生了等待

都是类似下面的语句,最高时,并发超过100.

SELECT 
    * INTO #Tmp from TB where 1=2

特点如下:

1.语句简单 开销都小于5不会产生并行

2.都采用了select into #temptable的形式

就像上面分析的一样,CMEMTHREAD等待是一个并发问题,而不是一个内存问题。在其他方案行不通的时候,我们可以通过调整此类语句的写法,减少CMEMTHREAD等待.

业务模型及架构

目前系统是单机运行的状态,这其实是很少见的。存在少量OLAP 和OLTP业务混合的情况。后续我们会给客户规划 读写分离 或者负载均衡的解决方案。在

 

解决方案

安装最新的补丁

至少需要安装前面发的解决等待问题的FIX。建议是直接安装到目前为止最新的2012 SP4补丁。

修改参数

optimize for ad hoc workloads 从0修改为1 。针对将即席执行计划ad hoc plans 插入到计划缓存中的时候 场景,减少ad hoc 查询占用的内存。

增加TEMPDB数据文件的个数

select * into #temptable 会产生大量的闩锁争用,防止在CMEMTHREAD 等待消除后,出现大量的pagelatch 闩锁争用。我经历过很多案例,解决了前面的一个拥堵之后,

后面有产生了新的等待,导致性能更差了。请记住优化是一个长期的,循序渐进的过程。

迁移TEMPDB数据文件的位置

目前部分tempdb文件放在S,一般分放在D盘。建议都迁移到S盘(存储上面),增加tempdb的响应速度。如果可能的话,使用SSD来最大化tempdb的性能,将会是不错的选择。

 

优化程序的代码

修改代码通常都是放在最后面的,因为要牵涉的情况比较多。前面的手段80%的情况下,都可以解决问题。剩下的20%,我们需要,检查程序中的逻辑,看看这些的语句都是什么业务产生的。什么条件会触发这类业务.对应下面类似的语句都使用存储过程,或者参数化后的方式,减少编译和重编译的次数。另外此类语句都会并发创建临时表,可能通过调整tempdb的设置,加快此类语句的执行速度,减少同一时间此类语句的并发数量。

 

优化效果

经过前面的几个优化手段,第二天开始,没有再出现过一次CMEMTHREAD的等待。

等待

 

 慢语句

 

总结

通过这篇文件你应该已经完全学会了数据库性能调优的思想。他告诉了我们出现问题时,怎么动手一步一步的排查问题,就像剥洋葱一样一层一层的剥开。

 

 

参考


微软官方博客对这类等待的原理和如何调试How It Works: CMemThread and Debugging Them 

 SQL Server 2016 对这里问题进行了进一步的优化,详细参考     SQL 2016 – It Just Runs Faster: Dynamic Memory Object (CMemThread) Partitioning

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
4月前
|
数据库
电子好书发您分享《《阿里云数据库案例集客户案例集》电子书》
电子好书发您分享《《阿里云数据库案例集客户案例集》电子书》
202 2
|
4月前
|
SQL 弹性计算 关系型数据库
服务器数据恢复-华为ECS云服务器mysql数据库数据恢复案例
云服务器数据恢复环境: 华为ECS云服务器,linux操作系统,mysql数据库(innodb引擎)。作为网站服务器使用。 云服务器故障: 在执行mysql数据库版本更新测试时,误将本应该在测试库上执行的sql脚本执行在生产库上了,生产库上的部分表被truncate,部分表内有少量数据被delete。 需要恢复被truncate的表以及被少量数据被delete的表。
服务器数据恢复-华为ECS云服务器mysql数据库数据恢复案例
|
2天前
|
NoSQL MongoDB 数据库
MongoDB数据恢复—MongoDB数据库文件被破坏的数据恢复案例
服务器数据恢复环境: 一台Windows Server操作系统服务器,服务器上部署MongoDB数据库。 MongoDB数据库故障&检测: 工作人员在未关闭MongoDB数据库服务的情况下,将数据库文件拷贝到其他分区。拷贝完成后将原MongoDB数据库所在分区进行了格式化操作,然后将数据库文件拷回原分区,重新启动MongoDB服务,服务无法启动。
|
14天前
|
SQL 存储 数据挖掘
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
服务器数据恢复环境: 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5,划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检: 由于未知原因,Sql Server数据库文件丢失,丢失数据涉及到3个库,表的数量有3000左右。数据库文件丢失原因还没有查清楚,也不能确定数据存储位置。 数据库文件丢失后服务器仍处于开机状态,所幸没有大量数据写入。 将raid5中所有磁盘编号后取出,经过硬件工程师检测,没有发现明显的硬件故障。以只读方式将所有磁盘进行扇区级的全盘镜像,镜像完成后将所
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
|
1月前
|
Oracle 关系型数据库 数据库
Oracle数据恢复—Oracle数据库误truncate table的数据恢复案例
北京某国企客户Oracle 11g R2数据库误truncate table CM_CHECK_ITEM_HIS,表数据丢失,业务查询到该表时报错,数据库的备份不可用,无法查询表数据。 Oracle数据库执行Truncate命令的原理:在执行Truncate命令后ORACLE会在数据字典和Segment Header中更新表的Data Object ID,但不会修改实际数据部分的块。由于数据字典与段头的DATA_OBJECT_ID与后续的数据块中的并不一致,所以ORACLE服务进程在读取全表数据时不会读取到已经被TRUNCATE的记录,但是实际数据未被覆盖。
Oracle数据恢复—Oracle数据库误truncate table的数据恢复案例
|
2月前
|
存储 SQL 数据库连接
连接并操作数据库:Python 数据库案例
数据库是一种用于存储和管理数据的工具,它以一种有组织的方式将数据存储在文件或内存中,以便于检索和处理。数据库系统通常使用 SQL(Structured Query Language)语言来进行数据的操作,包括数据的插入、查询、更新和删除等。
|
2月前
|
存储 Oracle 关系型数据库
【数据库数据恢复】Oracle数据库ASM磁盘组掉线的数据恢复案例
oracle数据库ASM磁盘组掉线,ASM实例不能挂载。数据库管理员尝试修复数据库,但是没有成功。
【数据库数据恢复】Oracle数据库ASM磁盘组掉线的数据恢复案例
|
3月前
|
SQL 关系型数据库 MySQL
Mysql高可用,索引,事务与调优:提高数据库性能的关键技术
在当今互联网时代,高可用性、稳定性和性能是数据库的三大关键要素。本文将深入探讨Mysql高可用、索引、事务和调优等方面的技术,为读者提供实用的解决方案和经验。
24 0
|
3月前
|
SQL Java 数据库连接
JDBC增删改查案例讲解
JDBC增删改查案例讲解
19 0

热门文章

最新文章