客服微信
作者:炎燚小寳
原文链接:TDPUB数加社区
环境
oracle:11.2.0.4
os:rhel6.9
前言
用户有条SQL跑出结果,还报ORA-01555的问题,我们看下这条SQL。
一、SQL文本
select a.kprq, a.fpdm, a.fphm, a.fpzt_bz, a.xfsbh, a.xfmc, a.xf_qxswjg_dm, a.gf sbh, a.gfmc, a.gf_qxswjg_dm, b.mc, b.ggxh, b.spbm, b.sl, b.jldw, b.dj, b.je, b.se, a.jshj from AA a, BB b where a.fpdm || a.fphm = b.fpdm || b.fphm and a.kprq >= to_date('20220901', 'yyyymmdd') and a.kprq <= to_date('20220930', 'yyyymmdd') and a.gfsbh in ('1', '2', '3', '4', '5', '6', '7', '8');
# 二、SQL执行情况
执行计划
三、问题分析及优化思路
从执行计划可以看出,该SQL主要问题就在于BB超大表的全表扫描,同时跟用户确认,该SQL最终返回结果不多。查看关联列,是有索引的,那为什么没有走索引?
仔细看SQL文本,发现关联条件是这样的:a.fpdm || a.fphm = b.fpdm || b.fphm,怪不得走不了索引,针对这样的写法,我们最好建议改下关联方式:a.fpdm = b.fpdm and a.fphm = b.fphm,最终用户接受了该方案。
如果代码写死无法改SQL咋办?也有办法,在被驱动表上创建一个以关联条件的虚拟列,在该虚拟列上创建索引即可优化,有兴趣的读者可以自行验证。
四、优化方案
(一)、改写SQL
(二)、被驱动表创建虚拟列,并在该列创建索引
五、优化效果对比
通过确认关键表数据量,制定执行计划,可以减少每次查询的逻辑读和物理读,提高SQL执行性能。
(一)、优化后的执行计划
略
(二)、优化前后资源消耗对比