技术开发 频道

一次惊心动魄的存储过程优化经历

    【IT168 技术文章】

    一个客户的DB2数据库遇到性能问题,一个存储过程执行时间特别长,分析如下:

    首先考察系统资源使用状况,IO/CPU/MEMORY等资源都没有瓶颈发生,从DB层面上考察,通过快照分析数据库几个大的指标:BUFFERPOOL命中率很高、

    没有排序溢出产生、有锁升级/锁等待现象;所以怀疑可能由于锁造成了执行存储过程的工作单元处于锁等待状态,没有继续执行下去;所以和开发人员配合

    对存储过程的执行进行鉴控:

    1、首先快照开关打开

    2、执行存储过程

    3、确定执行存储过程的工作单元

    4、鉴控工作单元的状态

    5、收集这个工作单元的快照信息

    经过对特定工作单元的鉴控,发现工作单元一直处于UOW Executing状态,也就是说,排除了由于锁等待造成执行时间长的可能性;经过大约5分钟,

    单独对这个工作单元采集了数据库快照进行分析,分析得到的具体情况是:

    1、BUFFERPOOL命中率很高、没有排序溢出产生、没有锁等待

    2、执行时间是0,因为存储过程还没有执行完成,所以执行时间为0

    3、插入、删除、更新均不超过50000行,但是rows read很高,达到1500000000行;通过以上分析,其他指标都正常,只有rows read很高,

    这个指标说明存储过程中包含的SQL在执行过程中可能发生了大量的FULL TABLE SCAN(如果通过索引的话,则满足条件的记录数才计算到rows read指标,

    如果通过FULL TABLE SCAN的话,则表的所有行数被计算到rows read指标),所以应该是存储过程本身执行的慢,需要优化存储过程;快照只能鉴控到(call 过程名字) 这样的SQL语句,过程里面的逻辑或者SQL语句对于我们是个黑盒子,鉴控不到包含在里面的SQL语句的执行状态信息(或许通过第三方工具Quest Center可以看到),我们可以使用事件监视器这样的工具来辅助我们分析过程中执行的静态SQL,事件监视器可以得到package/section信息,通过package/section信息我们可以从CATALOG中得到实际具体执行的SQL语句,然后可以分析它。怀疑存储过程执行慢可能是由于以下几个原因造成的:

    1)SQL语句中可能在大表之间发生了JOIN (这个JOIN通常会很慢,2个10万条记录的表发生JOIN,在NESTED LOOP情况下,需要JOIN 10000000000次,

    在HASH JOIN的情况下,则会快一些)

    2)大量的重复计算(比如有一个循环逻辑,循环语句块包含的大SQL中部分中间结果集(比如子查询)相同,每次循环都要重复计算一次,造成极大的浪费;

    所以说,可以把这个中间结果集提前计算出来,保存到临时表中)

    3)存储过程算法不优化

    既然怀疑存储过程问题,所以我们应该检查存储过程体,通过修改逻辑或者优化SQL(通过一些工具,比如Visual Explain、db2adivs、db2batch工具等),将可以优化的地方优化一遍,从而逐步解决性能问题。通过检查存储过程,最后发现是其中的SQL写的有问题,导致执行特别慢.

    注:

    1.当所有工作单元性能都不好时,需要从宏观上找原因(比如调整操作系统参数、数据库堆栈参数、缓冲池分配等,优化设计、优化糟糕的SQL等);

    而当其中某个工作单元性能不好,其他工作单元性能正常时,那么则需要单独鉴控这个性能不好的工作单元的状态信息,找到影响性能的原因

    (比如锁的问题;或者本身程序问题,执行效率不高).

    2.收集性能快照时,需要采集一个或者几个时间段的数据(比如30分钟为一个时间段),这个时间段不能太短,不然收集的性能数据不能准确反映数据库的实际

    运行情况,譬如:1分钟时间段的快照得到的BUFFERPOOL命中率可能为99%,30分钟时间段的快照得到的BUFFERPOOL命中率可能低于90%,相对来说,BUFFERPOOL命中率低于90%更接近于实际情况,所以应该按照这种情况来分析调优;相反如果按照BUFFERPOOL命中率99%的情况来分析的话(99%命中率表明BUFFERPOOL使用上不存在问题),就偏离了方向了。
 

0
相关文章