一个SQL引发的性能问题

一个性能测试项目,一个值得深思的问题。

1.症状:

12小时稳定性压测,压力恒定

系统响应时间随压测时间的增长而不断增大

如图所示:

2.性能分析,性能问题定位

1)         系统负载检查:在压测过程中,压力恒定,CPU 利用率没有较大的波幅

2)         磁盘IO检查:在压测过程中,磁盘读写稳定,没有较大的请求等待队列

3)         网络检查:在压测过程中,无较大的数据传输,网络延迟正常,测试环境的网络正常。

4)         内存检查:系统可用内存逐渐减小,JVM内存逐渐增大,不排除随着压测时间的增大而JVM崩溃的极端情况发生。

通过分析jvm dump发现,在测试结束时,jvm内存在较多的与JDBC通信的等待线程。此类线程占用了较多的JVM内存空间

根据上面的第4点,初步判断是与db的交互出现了性能问题。

转到DB查看性能监控日志,对比测试开始和测试结束时的性能日志,发现其中一条SQL的查询性能差别极大。在初始时查询响应时间在10ms以下,但在测试结束时,达到800多毫秒,增幅达到80多倍,占据了整个transction响应时间的95%。

获取该SQL的DB执行计划:

可见该SQL在查询过程中使用了表扫描的操作,该操作的cost为2898,占据了99%的执行时间。

再查询该表的大小, 发现该表在测试开始时仅有一千条左右的记录,但在测试结束时,已经增加到了30万条左右的记录,由此,真相大白,在测试刚开始时,表数据记录较少,即使使 用表扫描查询,DB响应也较快,但随着测试的进行,表中的记录迅速增长,此时,表扫描的性能迅速下降,成为性能瓶颈.

3.性能调优

知道了问题所在,解决起来就容易了

SQL使用表扫描进行查询,是缺少了对应的索引,为此,我们给它建立了恰当的索引,在建立索引后,再查看该SQL的执行计划:

如图所示,先前的Table access full 已经变为table access by index rowed ,消耗的资源由2898降低到4,完全解决了性能瓶颈。此时,再进行12小时的稳定性压测,系统性能稳定,不再出现响应时间不断增长的现象。

通过该案例,可以得到一条有用性能经验,在记录增长较快的表中,即使初始查询的响应很快,也要为查询SQL建立合适的index,避免DB因为使用不恰当的执行计划而导致不必要的性能开销,从而避免系统产生数据查询上的性能瓶颈。

时间: 2024-10-10 10:32:38

一个SQL引发的性能问题的相关文章

悠然乱弹:一段SQL引发的性能危机及其背后隐藏的设计缺陷

有个同学,说是系统中出现性能问题了,说是让我帮助诊断一下.本来是不想花这时间的,结果耐不住对方的死缠乱打,只要答应帮看看. 故事发生的背景是,在文件上传的时候,有时间会有人上传了文件,但是最后没有使用上传的文件,这样就会产生一些垃圾文件. 原来软件作者就想写一个后台定时任务程序,来清除这些垃圾文件? 由于作者坚定的不让我发她的SQL语句(这个我也理解,这么丑陋的SQL),所以这里就不发源代码了,发伪代码. void deleteMissLinkFile{ List fileList=getFil

《开源框架那些事儿27》悠然乱弹:一段SQL引发的性能危机及其背后隐藏的设计缺

有个同学,说是系统中出现性能问题了,说是让我帮助诊断一下.本来是不想花这时间的,结果耐不住对方的死缠乱打,只要答应帮看看.  故事发生的背景是,在文件上传的时候,有时间会有人上传了文件,但是最后没有使用上传的文件,这样就会产生一些垃圾文件. 原来软件作者就想写一个后台定时任务程序,来清除这些垃圾文件? 由于作者坚定的不让我发她的SQL语句(这个我也理解,这么丑陋的SQL),所以这里就不发源代码了,发伪代码. 123456789101112131415 void deleteMissLinkFil

Oracle数据库该如何着手优化一个SQL

这是个终极问题,因为优化本身的复杂性实在是难以总结的,很多时候优化的方法并不是用到了什么高深莫测的技术,而只是一个思想意识层面的差异,而这些都很可能连带导致性能表现上的巨大差异.所以有时候我们应该先搞清楚需求到底是什么,SQL本身是否合理,这些思考很可能会使优化工作事半功倍.而本文是假设SQL本身合理,从Oracle提供给我们的一些技术手段来简单介绍下Oracle数据库,该如何使用一些现有的技术来优化一个SQL执行的性能. 确定需要优化的SQL文本及当前SQL执行计划 确定SQL涉及的所有表及其

Mysql中where条件一个单引号引发的性能损耗

日常写SQL中可能会有一些小细节忽略了导致整个sql的性能下降了好几倍甚至几十倍,几百倍.以下这个示例就是mysql语句中的一个单引号('')引发的性能耗损,我相信很多朋友都遇到过,甚至还在这样写. 先看下我的表结构: CREATE TABLE `d_sku` ( `id` varchar(36) NOT NULL, `commodity_id` varchar(36) DEFAULT NULL, `counts` int(11) DEFAULT NULL, `price` double(15,

新建一个索引能够同时提升三条SQL的查询性能

如题 CREATE TABLE `score` (   `id` int(11) NOT NULL,   `studentid` int(11) NOT NULL,   `subjectid` int(11) NOT NULL,   `score` int(11) NOT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- 新建一个索引能够同时提升三条SQL的查询性能 ALTER TABLE `score` AD

SQL Server中一个隐性的IO性能杀手-Forwarded record

原文:SQL Server中一个隐性的IO性能杀手-Forwarded record 简介     最近在一个客户那里注意到一个计数器很高(Forwarded Records/Sec),伴随着间歇性的磁盘等待队列的波动.本篇文章分享什么是forwarded record,并从原理上谈一谈为什么Forwarded record会造成额外的IO.   存放原理     在SQL Server中,当数据是以堆的形式存放时,数据是无序的,所有非聚集索引的指针存放指向物理地址的RID.当数据行中的变长列增

一个神奇SQL引发的故障【转】

前几天一个客户数据库主实例告警,诊断过程中发现是由一个慢SQL导致的数据库故障,而在排查逐步深入之后却发现这个现象的不可思议. 问题描述 2016年12日09日,大概9点26分左右,一个客户的生产库主实例发出告警,告警信息如下: MySQL实例超过五分钟没有更新.这个告警信息简单解释下就是持续五分钟无法获取该实例的信息. 同时开发人员还反映,从12月09日凌晨1点开始,已经出现一些数据库请求超时的现象,直到出现告警信息之后业务恢复正常. 问题排查 1.监控进程排查 该数据库系统使用袋鼠云Easy

SQL Server 2008性能故障排查(二)——CPU

原文:SQL Server 2008性能故障排查(二)--CPU 承接上一篇:SQL Server 2008性能故障排查(一)--概论 说明一下,CSDN的博客编辑非常不人性化,我在word里面都排好了版,贴上来就乱得不成样了.建议CSDN改进这部分.也请大家关注内容不要关注排版.同时在翻译的过程中本人也整理了一次思路,所以还似乎非常愿意翻译,虽然有点自娱自乐,但是分享给大家也是件好事 CPU 瓶颈: CPU瓶颈可能因为某个负载所需的硬件资源不足而引起.但是过多的CPU使用通常可以通过查询优化(

和表值函数连接引发的性能问题

原文:和表值函数连接引发的性能问题     最近调优过程中遇到一个问题,就是表值函数作为连接中的一部分时,可能会引起麻烦,本文会简单阐述表值函数是什么,以及为什么使用表值函数进行连接时会引发性能问题. 表值函数     SQL Server中提供了类似其他编程语言的函数,而函数的本质通常是一段代码的封装,并返回值.在SQL Server中,函数除了可以返回简单的数据类型之外(Int.Varchar等),还可以返回一个集合,也就是返回一个表.     而根据是否直接返回集合或是定义后再返回集合,表