银行oracle生产故障,由SELECT *引发的多个生产故障,问题藏太深了吧……

66901039fe4385a74b9fe7500f577cae.png案例 1f3f9343774e5cc9995f05852e1aea090.png

用户反馈生产环境有两条SQL语句,可以确认区别只有表名的不同(实际参数相同),但性能上却有10倍以上的差距。

a7a64664bceb85ddc8b33d2fe1aac639.png

通过生成的监视报告可发现SQL1执行时间8s,IO 403MB,如下图:

aa10a0c80bdb7d6cee328c5685d0c782.png

SQL2 执行时间2.1m,IO则有15GB,如下图:

f8ad95010049431217a0f606d2d524f7.png

根据业务反馈,SQL1中表是影子表,数据量,表结构跟对应表几乎相同,那么为什么执行时间差距这么大呢?

DBA在此之前已经在准生产环境多次通过DBMS_SHARED_POOL.PURGE

删除对应的执行计划,换参数多次重复解析,均没获得正确的执行计划。

通过分析对比监视报告发现,SQL1中with语句正常物化,执行计划中存在临时表转化操作,即TEMP TABLE TRANSFORMATION

,而SQL2中由于没做临时表转化操作,IM_HISMESSAGE

表被访问多次,效率低下。

9692853a3efedff21550f3209c7a1edf.png

通过再次观察整个SQL运行期间的等待事件,我们可以快速发现,其实SQL慢了10倍的原因并非是执行计划引起的(主要等待事件为直接路径读,读写临时表比例很低,而且并没有出现经典的大表作为NL被驱动表的情况),对比运行数据,可以发现IO的增量主要来源于对IM_HISMESSAGE

表的扫描。

影子表的差异

通过逐行对比号返回列的详细信息,我们终于发现了谜底:

原始表是有LOB字段的,影子表没有LOB字段,IO量小了很多。同时由于存在LOB字段,with语句无法进行临时表转化。

而SQL文本中经典的 select则完美的掩盖了这一差异,开发人员图方便写出来的 select * 查询了根本不需要的LOB字段,导致了性能的急剧下降。

66901039fe4385a74b9fe7500f577cae.png案例 2f3f9343774e5cc9995f05852e1aea090.png

客户生产环境的AWR报告上有一条夸张的TOPSQL,占全天DBTIME的84%

5160eb11cafd0dec36019483f39d004d.png

原始SQL不展示了,SQL本身其实比较简单,模拟下来如下:

select * from test_a where object_id =11;

执行计划也很简单,所以很快也能发现问题,TABLE ACCESS BY INDEX ROWID

的COST相对异常的高,排查下表的统计信息时,惊奇的发现,这是张宽表,有400+列,当宽表遇上select *

时,性能就急剧下降了。

e22b3bf670b4c954ddff974f12de3fdc.png

c9992f12d11886ac816b700518ac0b91.png

问题定位虽然很快,但处理起来却并不方便,毕竟需要找到开发改SQL,这快不了。当然没什么疑问的是,系统的性能问题出在SQL代码的质量。

66901039fe4385a74b9fe7500f577cae.png案例 3f3f9343774e5cc9995f05852e1aea090.png

准备环境如下:从dba_objects

中复制两张表t1,t2作为测试环境表。

1357a358854ba4685378ee73dee5d77f.png

准备了两个查询,相同的条件,区别主要在于一个只查单列,另外一个查询全列。

通过模拟,可以发现,use_merge

这种表连接方式情况下,排序操作的内存消耗有较大的差距,这种差距会在有索引情况下,且指定查询列也能命中索引走索引快速全扫描时被大幅放大。

查询全列,SORT JOIN

内存消耗 1810K:

d24315059a18db7420a30b3ba6836596.png

aad24fb59b24079583b127ff896a5cd7.png

查询id,SORT JOIN

内存消耗 424K:

4ebf25e2779d9bc6b8f4589f3c81c1cc.png

e19b83c3cf2d39a08856d8ba11249aed.png

如果是HASH JOIN的话,join操作影响相对较小,可以换hint再测试看看。

66901039fe4385a74b9fe7500f577cae.png案例 4f3f9343774e5cc9995f05852e1aea090.png

有些场景,SQL查询的表数据量较大,查询字段也较多(无法全部走索引)的时候,这里暂时不考虑*

增加的不需要使用的列在数据库返回数据到应用时网络层的消耗。

如果你的机器刚好是EXADATA,那么smart scan

也会让select *

与指定列的查询有明显的性能差异。

这个限于篇幅推荐直接参考Oracle官方技术博客:https://blogs.oracle.com/exadatacn/exadata-v5

66901039fe4385a74b9fe7500f577cae.png总结f3f9343774e5cc9995f05852e1aea090.png

通过这些案例,select *

这个规则,变得立体了许多。

select *

写法方便快捷,但带来的问题却藏得很深,这种问题在上线后,随着系统的维护,都将变成修复成本极高的隐患。

SQL审核做得好,数据库性能不再是烦恼~至于其他关于数据库的痛难点,不妨来DAMS中国数据智能管理峰会找找解决方案,峰会专设【数据库分场】,部分议题如下:《从自研演进看分布式数据库》中国银联 云计算中心团队主管 周家晶

《开源数据库MySQL在民生银行的应用实践》民生银行 项目经理 徐春阳

《如何构建数据库容器化PaaS》爱可生 资深方案架构师 徐阳扫码享受限时优惠,一起在数据库变迁中站稳脚跟!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 由于ARCHIVE导致数据库死 2 NIT文件中SGA区设置太大,导致内存不够用,数据库和系统都死 3 由于临时表空间无法扩展导致数据库被起 4由于未打补丁导致RMAN备份时将数据库起 5由于BLOB类型的表记录数太多操作又太频繁导致数据库效率急差 6由于未对特大表(达到或超过100万条记录)定期做表分析导致数据库操作特别慢 7由于空间不够导致插入数据时扩展索引失败 8由于REDOLOG破坏导致数据库异常 9由于控制文件被破坏导致数据库无法正常启动 10由于数据文件丢失或破坏导致数据库无法正常启动 11由于空间参数设置不合理导致扩展表空间、索引等失败 12由于时间格式的环境变量设置问题导致话单无法入库 13由于大事务未使用大回滚段导致事务起 14由于数据库连接数太多导致服务器进程数多或内存耗尽 15由于使用了MTS方式,导致数据库操作特别慢(包括备份) 16由于存在一个大事务操作,导致数据库性能特别差或产生频繁日志切换 17由于没有COMMIT,导致数据库表被锁住 18索引创建不合理,导致数据库查询特别慢 19 由于BUFFER参数设置不合理导致EXP失败 20由于EXP不向上兼容,语言不兼容,导致不同版本、不同字符集的数据库无法导入 21 由于创建表空间时误将其创建在以‘本地管理’,导致在表空间上的所有对象无法修改其存储参数 22 错误地在系统表空间上建无关的数据文件 23 ORACLE客户端在P4上安装不成功 24由于LISTENER.ORA或TNSNAMES.ORA配置问题导致网络问题 25由于环境变量设置问题导致VERSOIN版本启动问题 26用户数据、表破坏下的数据恢复 27 由于OS层问题导致数据库ORA-600错误 .....

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值