oracle 神奇的merge into

我的问题:

oracle 神奇的merge into_第1张图片

oracle 神奇的merge into_第2张图片

你们看我这个,1号的就走索引,4号的不走索引要全表,我希望4号走索引,加了强制走索引的语句也不管用,怎办?

(我的语句:)

update  t_mt  partition(P_MT5_1) mt set (mt.stat,mt.rpttime)=(select stat,rpttime from t_statbuf buf 
 where sj>=to_date('2013-05-04 00:00:00','yyyy-mm-dd hh24:mi:ss') and sj=to_date('2013-05-04 00:00:00','yyyy-mm-dd hh24:mi:ss') and mt.ctime=to_date('2013-05-04 00:00:00','yyyy-mm-dd hh24:mi:ss') and sj

大神(名次)说:

这个你最好用merge into 的方式。
这个两个表做关联再去做更新的,而update 这个你要做两次查询也,而且多字段更新效果比较差
修改后的sql:
merge into t_mt  partition(P_MT5_1) mt  
using (select * 
            from  t_statbuf 
            where sj>=to_date('2013-05-05','yyyy-mm-dd') 
            and sj=to_date('2013-05-05','yyyy-mm-dd') 
and mt.ctime

结果:
我用的自己上面那个sql更新了20多分钟还没有结果,下面这个(怎么这么快!!~!):
66334 行,
121777 行,

然后继续问:

merge into 能删数据吗?那些被改过的数据,另一个表是要删掉的 ,用我原来的语句删,还是全表

答:

merge into 删除要看oracle版本的,版本高的是可以的

如果中途报错:
oracle 神奇的merge into_第3张图片

这个是你更新的表记录不唯一导致的

我自己写的:

1.更新mt中有状态的,mx没取的到mx,从4-27号开始,大概更新200万行,预计时间30分钟:

merge into t_busi_presend_mx  mx
using (select * 
from  t_mt 
where ctime>=to_date('2013-04-27','yyyy-mm-dd') 
)  mt 
on(mx.id=mt.mcid)
when matched then
update set mx.sjsendstatus=mt.stat,mx.rpttime=mt.rpttime
where  mx.cjsj>=to_date('2013-04-27','yyyy-mm-dd') 
and mx.sjsendstatus='NONE'

2.删除buf(204万)中msgid和mt(千万)中msgid相同的记录:

1.用的merge,删除200万条,用了535秒。(merge delete时,前面必须加update set)

merge into t_statbuf buf  
using (select * 
            from  t_mt 
            where ctime>=to_date('2013-04-27','yyyy-mm-dd') 
            )  mt
on(buf.msgid=mt.msgid)
when matched then
update set buf.stat=null
delete where( buf.msgid=mt.msgid)

2.我没有测试,但是别人虚拟的,并且也有关联的,只用了几十秒,所以貌似删除的时候应该不用merge,直接exists

可以这样试试:

create table tmp_t1 nologgng as
select buf.msgid from buf,mt where buf.id=mt.id;
create table tmp_mt nologging as
select * from mt;
create index ... on tmp_mt(msgid);
delete from tmp_mt mt where exists
(select 1 from tmp_t1 t1 where mt.msgid=t1.msgid);
commit;
delete from buf where exists
(select 1 from tmp_t1 t1 where buf.msgid=t1.msgid);
commit;
insert into buf 
select * from tmp_mt;
commit;

DELETE   t_statbuf m2 WHERE EXISTS(SELECT m1.msgid FROM t_mt m1 WHERE ctime>=to_date('2013-04-27','yyyy-mm-dd') AND m1.msgid=m2.msgid)

前人的经验:

merge 是比较实用,但是如果你遇到很大的数据量的更新,merge的效率也变差,你可能要做分批更新的操作,当然这种更新量也在千万级别的数据量 。

如果删除的数据小  buf和mt数据量大,就先把相同数据取出来,再用exists。

update每一条都要扫描一次

两个数据量相等的结果集,HASH JOIN 要快。

关联的结果集多 hash是快  关联的结果集少hash就慢。
两个数据差异不大的时候  关联结果集多才快  有时候两个数据表数量差异很大的时候hash也很慢  不过我试过,这种跟nested差别好像不是很大。

问:
什么叫差异不大
答:
数据量差不多
问:
几千万A 和 几亿B表 ?
hj(hash join)快些吧
如果几千 A和 几百万B当然NL(nested loop)快了
答:
如果数据关联结果集只有几百万那还是很慢的
看结果集数量
问:
结果集数量?
答:
嗯  关联的目标结果count数





你可能感兴趣的:(Oracle)