您好,欢迎访问一九零五行业门户网

Oracle Acs资深顾问罗敏 老罗技术核心感悟:自动扫描SQL语句工具

作者为:? shoug成员 – oracle acs高级顾问罗敏 问题和需求 “你们oracle公司有这样的自动扫描sql语句工具吗?通过这个工具,把我们的应用软件输进去,就能扫出sql语句的大部分问题。这样就可以减少我们测试和性能优化工作量,更能避免投产之后才暴露性能问
作者为:?
shoug成员 – oracle acs高级顾问罗敏问题和需求“你们oracle公司有这样的自动扫描sql语句工具吗?通过这个工具,把我们的应用软件输进去,就能扫出sql语句的大部分问题。这样就可以减少我们测试和性能优化工作量,更能避免投产之后才暴露性能问题。” — 来自某移动客户的需求。
“老罗,xx移动公司希望我们oracle公司提供自动扫描sql工具,我们有吗?听说第三方公司有这样的产品,已经在客户那儿试用了。” — 来自oracle服务销售同事的担忧。
是啊,客户的需求再合理不过。但据我所知,oracle公司好像没有这样包治百病的神奇工具。第三方公司居然有这样的工具,太吸引客户眼球了,一方面让人感到质疑,另一方面也令人感到一种竞争压力。
初识庐山真面目于是,我和销售同事趁去该客户现场拜访、调研的机会,对该客户的上述需求和第三方公司的自动化工具一探究竟了。客户的需求不必多言了,我们关键是对所谓自动化工具充满好奇。因商务因素,客户并没有给我们直接展示该工具的使用过程和界面,但告诉我们大致原理:原来该工具首先通过定义一组评分规则,例如:sql语句是否使用绑定变量;条件字段前是否有函数;多表连接是否超过4个表… …,然后将输入的sql语句进行评判,若违反这些规则,扣分!最后给该sql语句和整个应用模块打分。
原来如此!这些规则在大部分情况下不无道理,例如,条件字段加函数,特别是在日期字段前加to_char函数:
to_char(dj_sz.jdrq, ‘yyyy.mm.dd’) between ‘2014.04.01’ and ‘2014.04.17’
就是一种非常初级、业余、错误的编程方式。正确方式应该是:
dj_sz.jdrq between to_date(‘2014.04.01’,’yyyy.mm.dd’) and to_date(‘2014.04.17’,’yyyy.mm.dd’)
但是,更多的规则值得商榷。例如,在oracle公司推荐的编程规范中,并不是所有sql语句都应该使用绑定变量的,而只是针对并发量大的小事务sql语句才应该使用绑定变量,而针对并发量小的大事务sql语句,特别是非常复杂sql语句,oracle公司建议是不要使用绑定变量。第三方的自动工具能分析出sql语句是高并发量还是低并发量访问,以及大事务和小事务吗?值得怀疑。
更为典型的例子是,其实oracle公司从来没有官方正式建议:一个sql语句不能超过4个表的连接。的确,多表连接可能导致性能不佳,但问题不在于连接表的多和少,而在于编程人员是否理解了oracle的nested loop、hash join等多种表连接技术原理和适应场景,以及在表连接中索引的设计原理。以下就是一个国内著名财务软件的典型sql语句:
select *
from (select rownum num, temp.*
from (select a.fid,
… …
a.playdeptname as playdeptnamecode
from t_claim_remittancerecord a
left join t_pay_remittype b on a.remittype = b.fid
left join t_pay_fundtype c on c.fid = a.amountscategory
left join t_org_department d on a.remitdepart =
d.finasyscode
left join t_org_department y on a.playdeptname =
y.finasyscode
and y.status = 1
left join t_org_employee f on f.empcode = a.addperson
left join t_org_department k on f.deptid = k.id
left join t_org_employee g on g.empcode = a.updateperson
left join t_org_employee h on h.empcode = a.claimman
left join t_bd_customer cus on cus.fnumber = a.customer
left join v_lms_supplier s on s.snumber = a.supplier
left join t_deposit_printer i on i.codenum = a.codenum
left join t_org_employee j on i.createuser = j.empcode
where 1 = 1
and a.accountname like ‘%’ || :1 || ‘%’
and a.claimstate like ‘%’ || :2 || ‘%’
and a.writeoffstate like ‘%’ || :3 || ‘%’
and a.reachamountdate between :4 and :5
and a.repealstate != 1
order by addtime desc, codenum) temp) t
where t.num
and t.num > :7
哇!该语句好复杂哦,连接的表多达10多个。若采用第三方公司的sql自动扫描工具。该语句一定被扣分甚至彻底枪毙了。可是,该语句实际运行情况如何呢?以下就是该语句的执行计划:
———————————————————————————————| id? | operation | name? | cost (%cpu)|
———————————————————————————————| 0 | select statement? | |? 14 (100)|
| 1 |? filter | |? |
| 2 | view? | |? 14 (8)|
| 3 |? count? | |? |
| 4 | view ?| |? 14 (8)|
| 5 |? sort order by? | |? 14 (8)|
| 6 | filter? | |? |
| 7 |? nested loops outer | |? 13 (0)|
| 8 | nested loops outer? | |? 12 (0)|
| 9 |? nested loops outer | |? 11 (0)|
|? 10 | nested loops outer? | |? 10 (0)|
|? 11 |? nested loops outer | | 9 (0)|
|? 12 | nested loops outer? | | 8 (0)|
|? 13 |? nested loops outer | | 7 (0)|
|? 14 | nested loops outer? | |? ?6 (0)|
|? 15 |? nested loops outer | | 5 (0)|
|? 16 | nested loops outer? | | 4 (0)|
|? 17 |? nested loops outer | | 3 (0)|
|? 18 | nested loops outer? | | 2 (0)|
|? 19 |? table access by index rowid| t_claim_remittancerecord? | 1 (0)|
|? 20 |? ?index range scan? | idx_tcr | 1 (0)|
|? 21 |? table access by index rowid| t_pay_remittype | 1 (0)|
|? 22 | index unique scan | pk_remittype_fid ?| 1 (0)|
|? 23 | table access by index rowid | t_pay_fundtype? | 1 (0)|
|? 24 |? index unique scan? | pk_fundtype_fid | 1 (0)|
|? 25 |? table access by index rowid? | t_deposit_printer | 1 (0)|
|? 26 | index unique scan | pk_t_deposit_printer? | 1 (0)|
|? 27 | table access by index rowid | t_bd_supplier | 1 (0)|
|? 28 |? index range scan | idx_bd_supplier_num | 1 (0)|
|? 29 |? table access by index rowid? | t_org_department? | 1 (0)|
|? 30 | index range scan? | idx_t_org_dpt_finasyscode | 1 (0)|
|? 31 | table access by index rowid | t_org_department? | 1 (0)|
|? 32 |? index range scan | idx_t_org_dpt_finasyscode | 1 (0)|
|? 33 |? table access by index rowid? | t_bd_customer | 1 (0)|
|? 34 | index range scan? | idx_bd_customer_num | 1 (0)|
|? 35 | table access by index rowid | t_org_employee? | 1 (0)|
|? 36 |? index unique scan? | uk_employee_empcode | 1 (0)|
|? 37 |? table access by index rowid? | t_org_department? | 1 (0)|
|? 38 | index unique scan | sys_c00797036 | 1 (0)|
|? 39 | table access by index rowid | t_org_employee? | 1 (0)|
|? 40 |? index unique scan? | uk_employee_empcode | 1 (0)|
|? 41 |? table access by index rowid? | t_org_employee? | 1 (0)|
|? 42 | index unique scan | uk_employee_empcode | 1 (0)|
|? 43 | table access by index rowid? ?| t_org_employee? | 1 (0)|
|? 44 |? index unique scan? | uk_employee_empcode | 1 (0)|
大家看到上述执行计划,首先不应感到畏惧,而应该从外观上感慨一下,那就是数据库的美感!大家看这个执行计划的形状多么对称和富有韵律感,也多像一把打开的美丽扇子。其次,大家一定要相信,外观充满美感的东西,本质上也应该不错,呵呵。的确,回到技术本质,我们发现虽然该语句涉及10多张表的连接,但实际运行效率效果非常高,例如cost才14,当然cost有不准确的时候。更重要的是,该语句每次表连接都非常漂亮地采用了nested loop连接技术,并且都合理地采用了被连接字段的索引。正是因为设计开发人员非常了解oracle表连接原理以及索引设计规范,所以才设计出了这样“又好吃、又好看”的sql语句。
可是,第三方公司的sql自动扫描工具却很可能滥杀无辜了。大家一定能相信一个原理:世界上一件事物的好坏不在于多和少,而在于其本身的对和错。若将此原理运用在多表连接技术方面,那就是:多表连接的好坏不在于连接表的多和少,而在于每次表连接的对和错。因为oracle表连接每次都是两个表进行连接,然后再进行第三个、第四个表的连接。若充分理解了oracle各种表连接技术、索引设计规范等,每次表连接都是高效的,再多的表连接也是合理的。反过来,若不了解oracle表连接技术和适应场景,即便是两个表的连接都会出问题。
少一点噱头,多一点务实此标题有点刺耳,甚至刻薄,但的确是本人有感而发。国内it市场也的确存在这种不太正常现象:面对客户某些看似合理,实则很难实现的需求,某些公司不是去合理引导客户,反而是一味迎合客户,甚至是推波助澜,更实质的目的还是出于商业考虑。但是,大家不知这是一种非常短视的行为吗?难道客户不会很快就验证出这种所谓sql自动扫描工具的有效性,甚至真伪性吗?既然如此,大家何必去费尽心机,去讨客户这种“好”?实际上很可能是既让客户失望,也毁自己声誉的事情。
性能分析和优化,特别是sql语句性能分析和优化,怎么可能只做静态的形式分析?而不做与实际系统和数据相关联的动态神式分析?记得有一年参加一个数据库技术大会,一位国外性能优化大师的演讲曾经让我非常震撼,他的演讲主题是性能优化与应用数据的关联性,整个演讲中,他未展现一个sql语句优化技术,而是大谈数据分布对sql语句访问性能的重要性,诸如按字段分析最大值、最小值、分组统计等,以及何时需要按bucket方式收集统计信息等。所谓的sql语句自动扫描工具,可能连客户实际系统都不连接,执行计划也不分析,客户数据更不了解,就能扫描出sql语句质量?的确有点像个乌托邦的东西。
再回到本文开头一个问题:“你们oracle公司有这样的自动扫描sql语句工具吗?”准确地回答是:oracle的确没有这种不看数据、不看执行计划的所谓自动扫描sql语句工具,但oracle公司自10g开始就提供了大量内置的sql优化工具,例如:addm、sql access advisor、sql tuning advisor、automatic sql tuning、sql profile、spa(sql performance analyzer)、spm(sql plan management)… …这些工具一个共同特点是不仅分析sql语句执行计划,而且分析统计信息,分析数据分布情况,分析索引设计情况等,综合各方面情况,给出一些更合理的sql语句优化建议。例如,11g的automatic sql tuning就是分析sql语句所访问表的统计信息是否过期、是否缺乏索引、是否可产生有效的sql profile信息、语句编写是否合理等。
再者,虽然oracle自动优化工具能有效分析和解决很多sql性能问题,但更多基础性,特别是与应用数据紧密相关的问题,还是需要应用设计开发人员从数据库模型规范化设计、 基础技术掌握、sql设计开发规范、应用软件质量控制、加强设计开发管理等层面和角度去加以解决。
总之,性能优化工作,特别是应用性能分析和优化工作,还是需要大家踏踏实实、一点一滴地做起,即便需要所谓自动化的工具,也建议大家优先考虑oracle公司本身自带的工具,毕竟这些工具是oracle产品的一部分,经过了严格测试,也为全球广大客户的大量实践所验证,是具有普遍适用性的东西。
还是以本节标题作为本文结尾:
少一点噱头,多一点务实!
related posts:
oracle acs资深顾问罗敏 老罗技术核心感悟:分表还是分区?oracle acs资深顾问罗敏 老罗技术核心感悟:牛! 11g的自动调优和sql profile【oracle cbo优化器】视图合并view merging技术 _complex_view_merging & _simple_view_merginggather more plan statistics by gather_plan_statistics hintlatch free:cache buffer handles造成的sql性能问题dba_hist_plan_operation_nameora-00600:[15570]内部错误一例oracle中可被并行化执行的sql操作unique index vs non-unique indexunion all returning wrong results? 原文地址:oracle acs资深顾问罗敏 老罗技术核心感悟:自动扫描sql语句工具?, 感谢原作者分享。
其它类似信息

推荐信息