(部分表名字段名做了替换)
select XXXXX
from t1 a
where 1 = 1
and a.flag = '0'
and a.flag2 = '1'
and exists (select 'x'
from t2 b
where b.startno <= t1_certno
and b.endno >= t1_certno
and balanceno in
(select c.balanceno
from t3 c
where 1 = 1
and c.proposalno = '50062000429971'))
order by a.t1_certno
逻辑读排第一。这个 SQL由于是范围扫描,因此只能走 SORT MERGE JOIN,几个小时都跑不出结果。
靠固定执行计划解决不了问题。
要解决问题只能改程序。
其实,给定 proposalno从 t3里搜出来的数据一般只有几行,而且每行数据的 startno和 endno也相差不远。
因此可以将 b.startno <= t1_certno and b.endno >= t1_certno改成t1_certno in “t3里每行的b.startno和 b.endno之间每一个值”。
也就是先找出所有的 t1_certno所有可能的取值,最后再通过索引从大表 t1找数据。
下面写了一个方案,开发可以根据需要改写成能和程序交互的方式,例如写成函数,返回 table类型的数据等。
set serverout on
declare
tmp t2.startno%type;
i number;
len int;
begin
for c1 in ( select startno, endno from t2 b where balanceno in
(select c.balanceno
from t3 c
where 1 = 1
and c.proposalno = '50062000429971')
) loop
i := to_number(c1.startno);
len := length(c1.startno);
while i <= to_number(c1.endno) loop
-- dbms_output.put_line(lpad(to_char(i), len, '0'));
for c2 in (
select 要查的字段
from t1 a
where 1 = 1
and a.flag = '0'
and a.flag2 = '1'
and t1_certno = lpad(to_char(i), len, '0')
order by a.t1_certno
) loop
dbms_output.put_line(c2.xxx||' '||c2.xxx||' '||c2.xxx||' '||c2.xxx||' '||c2.xxx||' '||c2.xxx||' '||c2.xxx);
end loop;
i:=i+1;
end loop;
end loop;
end;
/

......
......
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26239116/viewspace-1392049/
,如需转载,请注明出处,否则将追究法律责任。