CBO面对in (1,2,3,……)或者类似的or操作会做些什么呢?
1. 把in转换为union all操作,从而用到索引加快查询,可以使用use_concat提示强制该转换,这么做的缺点在于CBO面对每个union all操作都要计算cost,导致parse时间过长,解决办法见2;
2. 对应的操作为inlist iterator,可以使用NO_EXPAND提示强制进行,即使用了索引,同时避免了union all带来的cost计算问题;
还有一个从设计角度优化这个问题的思路:就是建表保存in数据,用join代替in操作。
话说从前有一个从excel导入到数据库中的功能,近来该功能“超级”缓慢,严重影响生产活动。
从告警日志中,可以找到一些线索:日志切换非常频繁,出现多处checkpoint not complete。
同时,在系统中查询产生redo最多的会话,正是上面提到的那个功能,导入不到1w条数据,竟然累计产生近10G的redo!!!
到这里,已经有理由怀疑是这个功能出现的问题,导致过多的redo,进一步产生checkpoint not complete等待;
OK,10046,终于找到了问题的根源:不合理使用的物化视图
在导入功能相关的数据库表上,建有一个物化视图,我们知道物化视图刷新可以on commit,on demand,而这里使用了on commit,而且每次都是全刷新;更糟糕的是,导入功能是每条记录提交一次!
也就是说:每导入一条数据,物化视图需要清空,重新刷新数据。
解决思路:
- 物化视图刷新模式修改为on demand
- 物化视图全刷新变为快速刷新
- 导入数据使用分批提交方式
昨天接到一个任务:一个报表相关sql语句需要优化,原来执行时间几分钟,现在半小时也出不来。
登录系统后,查看sql语句执行计划未发现问题;
会话A中执行语句,A会话的状态为inactive,相关等待事件为SQL*Net message from client;
上面的现象比较怪异,值得怀疑;
进一步查看sql语句,发现select后面有部分列使用了自定义函数,试图去掉自定义函数相关字段,查询,很快正常返回结果;
到这里可以断定是函数导致的问题,经过进一步针对自定义函数以及表中相关列数据的排查,最后确定问题的原因:
对于表中一条特殊数据,自定义函数进入死循环,故sql语句长时间未返回。
问题函数,看看死循环在哪呢:
create or replace function P_StringReplace(Src in varchar2) return varchar2 as
Result varchar2(2000) := '' ;
tempstr varchar2(2000) := '';
tempstr2 varchar2(2000) := '';
begin
tempstr := '';
tempstr2 := '';
if (Src is not null) then
begin
tempstr := substr(Src,instr(Src,'=')+1);
loop
if instr(tempstr,';')<=0 then
exit;
end if;
tempstr2 := substr(tempstr,instr(tempstr,';'),instr(tempstr,'=')-instr(tempstr,';')+1);
tempstr := replace(tempstr, tempstr2, '/');
end loop;
Result := tempstr;
end;
else
begin
Result := '无';
end;
end if;
return(Result);
end P_StringReplace;