系统性能调优方案_第1页
系统性能调优方案_第2页
系统性能调优方案_第3页
系统性能调优方案_第4页
系统性能调优方案_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 系统性能调优方案DBAplus社群 微信号 dbaplus功能介绍 围绕数据库、大数据、PaaS云,顶级大咖、技术干货,运营几个月受众过十万!成为运维圈最专注围绕“数据”的学习交流和专业社群!欢迎投稿,加入探讨。性能优化是一个老生常谈的问题了,典型的性能问题如页面响应慢、接口超时,服务器负载高、并发数低,数据库频繁死锁等。而造成性能问题又有很多种,比如磁盘I/O、内存、网络、算法、大数据量等。我们可以大致把性能问题分为四个层次:代码层次、数据库层次、算法层次、架构层次。下面我会结合实际性能优化案例,和大家分享下性能调优的工具、方法和技巧。先说心态说到性能问题,你可能首先就想到的是麻烦或者头大

2、,因为一般性能问题都比较紧急,轻则影响客户体验,重则宕机导致财务损失,而且性能问题比较隐蔽,不易发现。因此一时间无从下手,而这时我们就很容易从心底开始去排斥它,不愿接这烫手的山芋。恰巧,性能调优也是体现程序员水平的一个重要指标。因为处理BUG、崩溃、调优、入侵等突发事件比编程本身更能体现平庸程序员与理想程序员的差距。当面对一个未知的问题时,如何定位复杂条件下的核心问题、如何抽丝剥茧地分析问题的潜在原因、如何排除干扰还原一个最小的可验证场景、如何抓住关键数据验证自己的猜测与实验,都是体现程序员思考力的最好场景。是的,在衡量理想程序员的标准上,思考力比经验更加重要。所以,若你不甘平庸,请拥抱性能调

3、优的每一个机会。当你拥有一个正确的心态,你所面对的性能问题就已经解决了一半。再说技巧拿到一个性能问题,不要忙着先上工具,先了解问题出现的背景,问题的严重程度。然后大致根据自己的经验积累作出预估。比如客户来了个性能问题说系统宕机了,已经造成资金损失了。这种涉及到钱的问题,大家都比较敏感,根据自己的Level,决定是否要接这个锅。这不是逃避,而是自知之明。了解问题背景后,下一步就来尝试问题重现。如果在测试环境能够重现,那这种问题会很好跟踪分析。如果问题不能稳定重现或仅能在生产环境重现,那就相对比较棘手,这时要立刻收集现场证据,包括但不限于抓dump、收集应用程序以及系统日志、关注CPU内存情况、数

4、据库备份等,之后不妨再尝试重现,比如恢复客户数据库到测试环境重现。不管问题能否重现,再下一步,我们要大致对问题进行分类,是代码层次的业务逻辑问题还是数据库层次的操作耗时问题,又或是系统架构的吞吐量问题。那如何确定呢?而我倾向于先从数据库动手。我的习惯做法是,使用数据库监控工具,先跟踪下SQL耗时情况。如果监控到耗时较长的SQL语句,那基本上就是数据库层次的问题,否则就是代码层次。若为代码层次,再研究完代码后,再细化为算法或架构层次问题。确定问题种类后,是时候上工具来精准定位问题点了:SQL耗时问题,推荐使用免费的Plan Explorer分析执行计划。代码问题定位,优先推荐使用VS自带的Per

5、formance Analysis,其次是RedGate的性能分析套件.NET Developer Bundle;然后还有Jet Brains的dotTrace - .NET performance profiler,dotMemory- .NET memory profiler;再然后就是反人类的Windbg等等。精准定位问题点后,就是着手优化了。相信到这一步,就是优化策略的选择了,这里就不展开了。优化后,最后当然要进行测试了,毕竟优化了多少,我们也要做到心里有谱才行。案例分享这里分享下针对代码层面、数据库层面和算法层面的优化案例。1. SQL优化案例案例1:客户反馈某结算报表统计十天内的数

6、据耗时10mins左右。由于前几天刚学会用RedGate的分析工具,拿到这个问题,本地尝试重现后,就直接想使用工具分析。然而,这工具在使用webdev模式起站点时,总是报错,而当时时一根筋,老是想解决这个工具的报错问题。结果,白白搞了半天也没搞定。最后不得已放弃工具,转而选择使用SQL Server Profiler去监控SQL语句耗时。一跟踪不要紧,问题就直接暴露了,整个全屏的重复SQL语句,如下图:SQL Profiler监控结果这下问题就很明显了,八成是代码在循环拼接SQL执行语句。根据抓取到SQL关键字往代码中去搜索,果然如此。看到这段代码,咱先不评判这段代码的优劣,因为毕竟代码注释清

7、晰,省了我们理清业务的功夫。这段SQL主要是想做去重处理,很显然选用了错误的方案。改后代码如下:改后测试相同数据量,耗时由10mins降到10s左右。2.代码优化案例案例2:客户反馈销售订单100条分录行,保存进行可发量校验时,耗时7mins左右。拿到这个问题后,本地重现后,监控SQL耗时没有异常,那就着重分析代码了。因为可发量校验的业务逻辑极其复杂,加上又直接再一个类文件实现该功能,3500+行的代码,加上零星注释,真是让人避之不及。逃避不是办法,还是上工具分析一把。这次我选用的时VS自带的Performance Profiler,开发环境下极其强大的性能调优工具。针对我们当前案例,我们仅需

8、要跟踪指定服务对应的DLL即可,使用步骤如下:Analyze-Profiler-New Performance Session打开Performance Explorer找到新添加的Performance Session,右键Targets,然后选择Add Target Binary,添加要跟踪的dll文件即可将应用跑起来选中Performance Session,右键Attach对应进程即可跟踪分析性能了在跟踪过程中,可随时暂停跟踪和停止跟踪图示步骤跟踪结束后本案例跟踪到的采样结果如下图:VS Performance Profiler分析报告同时Performance Profiler也给出

9、了问题的建议,如下图:VS Performance Profiler分析提示其中第1、4条大致说明程序I/O消耗大,第一代的GC上存在未及时释放的垃圾占比过高。而根据上图的采样结果,我们可以直接看出是由于再代码中频繁操作DataTable引起的性能瓶颈。走读代码发现的确如此,所有的数量统计都是在代码中循环遍历DataTable进行处理的。而最终的优化策略,就相当于一次大的重构,将所有代码中通过遍历DataTable的计算逻辑全部挪到SQL中去做。由于代码过多,就不再放出。案例3:客户反馈批量引入1000张订单,耗时40mins左右,且容易中断。同样,我们还是先尝试本地重现。经测试批量引入101

10、张单据,就耗时5mins左右。下一步打开SQL监控工具也未发现耗时语句。但考虑到是批量导入操作,虽然单个耗时不多,但乘以100这个基数,就明显了。下面我们就使用RedGate的Ants Performance Profiler跟踪一下。该工具比较直观,可以同时监控代码和SQL执行情况。第一步,New Profiler Session,第二步进行设置,如下图。根据自己的应用程序类别,选择相应的跟踪方式。跟踪设置针对这个问题,我们跟踪到的调用堆栈和SQL耗时结果如下图:调用堆栈监控结果SQL监控结果首先从调用堆栈中的Hit Count,我们可以首先看出它是一个批量过程,因为入口函数仅调用一次;第二

11、个我们可以代码中是循环处理每一个单据,因为Hit Count与我们批量引入的单据数量相符;第三个,突然来了个10201,如果有一定的数字敏感性的话,这次性能问题的原因就被你找到了。这里就不卖关子了,101 x 101 = 10201。是不是明白了什么,存在循环嵌套循环的情况。我们走读代码确定一下:好吧,外层套了一个空循环却什么也没做。修改就很简单了,删除无效外层循环即可。3.算法优化案例案例4:某全流程跟踪报表超时。这个报表是用来跟踪所有单据从下单到出库的业务流程数据流转情况。而所有的流程数据都是按照树形结果存储在数据库表中的,类似这样:图中的流程为:销售合同-销售订单-发货通知单-销售出库单

12、为了构造流程图,之前的处理方法是把流程数据取回来,通过代码构造流程图。这也就是性能差的原因。而针对这种情况,就是考验我们平时经验积累了。对于树形结构的表,我们也是可以通过SQL来进行直接查询的,这就要用到了SQL Server的CTE语法来进行递归查询。仔细观察上面的表结构,会发现其树形结构的特点:FFIRSTNODE:标记是否为根节点FSTABLENAME:标记来源单据名称FSID:标记来源单据分录IDFTTABLENAME:标记目标单据名称FTID:标记目标单据分录ID首先想到的办法就是把流程数据取回来,然后代码构造流程图。第一个思路:根据根节点循环往下找,吭呲半天,发现没那么简单。因为任

13、何一个源头单据都可以多次下推目标单据。第二个思路:先找到终极节点,在从终极节点往上找只至根节点为0。这个思路实现起来也没有那么复杂,逻辑理清,循环遍历,最终也能实现结果。(但在大数据量情况下,易导致性能瓶颈。)这一次我们换一个思路,让SQL来替我们做这一复杂的递归查询。1SQL Server 递归查询基本概念公用表表达式(CTE) 可以认为是在单个 SELECT、INSERT、UPDATE、DELETE 或CREATE VIEW 语句的执行范围内定义的临时结果集。公用表表达式可以包括对自身的引用,这种表达式称为递归公用表表达式。创建递归查询。在不需要常规使用视图时替换视图,也就是说,不必将定义

14、存储在元数据中。启用按从标量嵌套 select 语句派生的列进行分组,或者按不确定性函数或有外部访问的函数进行分组。在同一语句中多次引用生成的表。MSDN上对CTE的介绍/zh-cn/sql/t-sql/queries/with-common-table-expression-transact-sqlT-SQL查询进阶-详解公用表表达式(CTE)/CareySon/archive/2011/12/12/2284740.htmlCTE 的基本语法结构如下:即三个部分:公用表表达式的名字(在WITH关键字之后)查询的列名(可选)紧跟AS之后的SELECT语句(如果AS之后有多个对公用表的查询,则只

15、有第一个查询有效)动手实践根据官网示例我们很简单就可以写出CTE语句应用于我们的应用场景:在查询中我们指定条件参数WHERETBIE.FTTABLENAME = T_SAL_ORDERENTRY AND TBIE.FTID = 121625,即可查询到指定节点的完整流程数据。其中在与公用表TEST_CTE进行关联时,我指定了两个条件CTBIE.FSID=CTE.FTIDAND CTBIE.FSTABLENAME = CTE.FTTABLENAME,因为不同类型的单据各有一套自增的ID,直接用ID进行关联迭代不可行。需要注意的是OPTION(MAXRECURSION10)是用来限制递归次数,以避

16、免无限递归导致数据库性能消耗严重。扩展:构造递归路径基于上一个查询,增加一列手动拼接递归路径。注意SQL中将PATH设置的类型为navarchar(4000),在union中,两边的表结构类型必须保持一致,否则会报错定位点类型和递归部分的类型不匹配。可参考此篇博文解决CTE定位点类型和递归部分的类型不匹配。(/ccding13/p/3515393.html)递归路径查询结果2Oracle 递归查询基本概念Oracle中的递归查询语句为start withconnect by prior,为中序遍历算法。可参考Oracle 树操作、递归查询(selectstart withconnect byp

17、rior)了解更多。(链接/yingsong/p/5035907.html)其基本语法是:selectcolname from tablenamestart with条件1connect by条件2where条件3条件1: 是根结点的限定语句,当然可以放宽限定条件,以遍历多个根结点,实际就是多棵树。条件2:是连接条件,其中用PRIOR表示上一条记录。比如CONNECT BY PRIOR Id = Parent_Id就是说上一条记录的Id 是本条记录的Parent_Id。条件3:过滤返回的结果集。PRIOR关键字运算符PRIOR被放置于等号前后的位置,决定着查询时的检索顺序。PRIOR被置于CO

18、NNECT BY子句中等号的前面时,则强制从根节点到叶节点的顺序检索,为自顶向下查找。如:CONNECT BY PRIOR Id=Parent_Id PIROR运算符被置于CONNECT BY 子句中等号的后面时,则强制从叶节点到根节点的顺序检索,为自底向上的查找。如:CONNECT BY Id=PRIOR Parent_Id PS:当CONNECT BY后指定多个连接条件时,每个条件都应指定PRIOR关键字。动手实践理清了用法,我们用Oracle来对查询一下业务流程。查询结果该流程为:销售订单-发货通知单-销售出库单-退货通知单-销售退货单其中在指定连接条件时,我指定了两个条件FSID= PRIOR FTID AND FSTABLE

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论