技术开发 频道

性能测试项目反思

  【IT168 评论】

  现在一说性能测试、性能调优,好多人首先想到的是用LOADRUNNER等测试工具,好像没有这些工具就不能进行性能测试就不能进行性能调优。真是这样的吗?其实工具固然重要,但更重要的是系统的分析、测试案例的设计。正好刚刚结束了一个软件性能测试的项目,有些感触,整理一下,也为了给大家一个参考。

  前段时间一直在搞自动化测试框架SAFS、STAF等方面的东西,那个确实比较难搞。领导突然安排去做一个性能测试项目,已经近4个月没有搞性能测试了,心里确实有点没有底。配置的人员也比较少,并且经验也不足。我们首先分析了系统架构、业务特点、运维数据。发现系统的性能和用户数的多少并没有太多的关系,初步确定是因为某些模块的程序编写有性能缺陷。在运行程序时,明显发现有些功能响应缓慢。因为时间比较紧,并且测试环境并不是独立供性能测试使用,功能测试也在同一环境下进行,并且还没有给我们开通数据库DBA权限和服务器操作系统的超级用户权限,限制非常多,所以我决定分两步进行,让其他同事编写性能测试案例和脚本,我来分析系统响应时间缓慢的原因,初步判断应该是数据库方面的原因。因为给我开通的数据库用户只有查询权限,所以我只能用SQL语句来查询。

  追踪后台运行的SQL,通过select sql_text,sql_id,users_executing,executions, loads from v$sqlarea;来查询后台正在执行的SQL,通过得到的SQL_ID查询SQL语句

  select * from v$sqltext where sql_id ='75yzszjxyrrva',然后根据HASH_VALUE得到完整的SQL,select * from v$sql where hash_value='2079055722'.捕获SQL后发现

  两条SQL语句运行较慢:

  1、select b.case_id,report_no,report_time,b.organ_id,realname,accident_time, reporter_name,accident_type,certi_type,register_id, recorder_id, certi_code, accident_status, has_image, accident_type, diff_date, to_char(max(ti2.scan_time), 'YYYY-MM-DD HH24:MI:ss') as scan_time from ( select distinct tcc.case_id,tcc.case_no as report_no,tcc.report_time,tcu.real_name as realname,tcc.accident_type, tcc.accident_time,tcc.register_id,tcc.reporter_name,trc.certi_type,trc.certi_code,tcc.accident_status,tcc.recorder_id,tcc.organ_id,tcc.case_type, sysdate - trc.insert_time as diff_date,decode(ti.case_id, null, -1, 1) as has_image from t_report_case trc ,t_claim_case tcc,t_customer tcu,t_image ti ,t_employee te where trc.case_id = tcc.case_id and tcc.case_id = ti.case_id(+) and tcc.register_id = te.emp_id and tcc.register_id = 3381221 and tcc.insured_id = tcu.customer_id(+) and tcc.case_status=4 and tcc.case_type = te.case_type )b , t_image ti2 where ti2.case_id(+)=b.case_id group by b.case_id,report_no, report_time, b.organ_id, realname, accident_time, reporter_name, accident_type, certi_type, register_id, recorder_id, certi_code, accident_status, has_image, accident_type, diff_date order by has_image desc,report_time asc

  执行用时6.672秒。

  2、( select tpp.prem_id,tpp.policy_id,tpp.fee_type,tpp.pay_mode, tpp.fee_status,tpp.actual_prem,tpp.due_time,tgp.holder_id as customer_id, tgp.send_code,tgp.policy_code as policy_code, tpp.policy_type, tpp.insured_id,tif.insured_num,' ' as notice_code from t_policy_prem tpp,t_group_policy tgp,t_insured_first tif where ((tpp.fee_status=0 and tpp.pay_mode in(1,2))or(tpp.fee_status in(0,3,4) and tpp.pay_mode=3)) and tpp.fee_type= :1 and tpp.insured_id=tif.insured_id(+) and tpp.policy_id=tif.policy_id(+) and tpp.policy_type = '2' and tpp.policy_id = tgp.policy_id and tgp.send_code = :2 ) union ( select tpp.prem_id,tpp.policy_id,tpp.fee_type,tpp.pay_mode, tpp.fee_status,tpp.actual_prem,tpp.due_time,tp.holder_id as customer_id, tp.send_code,tp.policy_code,tpp.policy_type, tpp.insured_id,tp.insurant_num as insured_num,' ' as notice_code from t_policy_prem tpp,t_policy tp where 1=1 and ((tpp.fee_status=0 and tpp.pay_mode in(1,2))or(tpp.fee_status in(0,3,4) and tpp.pay_mode=3)) and tpp.insured_id is null and tpp.policy_type in ('1','3') and tpp.fee_type= :3 and tp.send_code = :4 and tpp.policy_id = tp.policy_id ) order by due_time,fee_type

  执行用时4.8秒左右。分析这两条SQL语句的执行计划,SQL1的COST值是一个天文数字,SQL2的COST的值是1700多,不算太高。明显第一条SQL语句需要优化,分析SQL1后

  建议优化为:select b.case_id,report_no,report_time,b.organ_id,realname,accident_time, reporter_name,accident_type,certi_type,register_id, recorder_id, certi_code, accident_status, has_image, accident_type, diff_date, to_char(max(scan_time), 'YYYY-MM-DD HH24:MI:ss') as scan_time from ( select distinct tcc.case_id,tcc.case_no as report_no,tcc.report_time,tcu.real_name as realname,tcc.accident_type, tcc.accident_time,tcc.register_id,tcc.reporter_name,trc.certi_type,trc.certi_code,tcc.accident_status,tcc.recorder_id,tcc.organ_id,tcc.case_type, sysdate - trc.insert_time as diff_date,decode(ti.case_id, null, -1, 1) as has_image,scan_time from t_report_case trc ,t_claim_case tcc,t_customer tcu,t_image ti ,t_employee te where trc.case_id = tcc.case_id and tcc.case_id = ti.case_id(+) and tcc.register_id = te.emp_id and tcc.register_id = 3381221 and tcc.insured_id = tcu.customer_id(+) and tcc.case_status=4 and tcc.case_type = te.case_type )b group by b.case_id,report_no, report_time, b.organ_id, realname, accident_time, reporter_name, accident_type, certi_type, register_id, recorder_id, certi_code, accident_status, has_image, accident_type, diff_date order by has_image desc,report_time asc

  修改后的执行用时是0.047秒左右。

  第二条SQL比较麻烦,通过用具体数据替代绑定变量执行速度很快,而在程序中却很慢,真的不知道是什么原因,与开发人员通过写日志逐行对代码进行检查,发现

  在receivedao.java文件中checkFullARSENDCODE(String s)函数中有这这行代码,

  preparedstatement.setLong(4, Long.parseLong(s));检查数据库,SENDCODE字段是字符型,传递的参数却是LONG型,

  更改为:preparedstatement.setString(4, Long.parseLong(s));

  效率明显提高,因为在SQL语句中传入的参数类型错误,如果传入的是长型就不走索引了,是全表扫描。这样的错误还真不好发现啊!

  通过这个例子,可以发现,不用自动化工具,不用编写脚本就可以发现一些明显的性能瓶颈的。

0
相关文章