一个资料库,数据容量总计为450GB.两个最大的表有6000万条记录
其中一个表字段数为65个,单条记录尺寸为1k--1.5k, 没有大对象(LOB).
现在需要通过其中的两个字段作为条件(已在其中建有索引),删除约50条记录.
数据库平台为RS6000 S7A, 内存2048M,  CPU:4*262MHZ. Orace8.1.5Enterprise
尝试过在小型机以脚本方式执行匿名块:
但下述脚本持续使用同一个回滚段,且不断增长,达10G, 最终因回滚段表空间
无法再分配下一下extent而失败. 怎样解决这种占用产生大量回滚实体的问题?
#!/bin/sh
svrmgrl << EOF
connect username/password;
alter table tb_name nologging;
declare
    v_id  tb_name.id%type;
    v_counter  number:=0;
    v_total number :=0;
    cursor V_Cur is
    select rkxh from tb_name where f_a=xxx and f_b=yyy;
begin
    open V_Cur;
  loop
    fetch V_Cur into v_id;
    exit when V_Cur%notfound;
          v_counter:= v_counter+1;
           delete from tb_name where id=v_id;
           v_total:= v_total + 1;
          if v_counter>=10000 then                  --10000条提交一次
             commit;
           v_counter := 0;
          end if;
  end loop;
        commit;
  close V_Cur;
exception
  when others then
    rollback;
    close V_Cur;
end;
/
alter session disable parallel dml;
alter table tb_name logging;
disconnect
exit
EOF

解决方案 »

  1.   

    不好意思,再修改一下:
    alter session enable parallel dml;
    alter table tb_name nologging;.....
    select id from tb_name where f_a=xxx and f_b=yyy;
      

  2.   

    不行啊,老兄。这么删除很慢的,估计跟我一样,开发时不太熟悉Oracle的分区功能吧。做成小的分区,管理就简单多了,现在正准备做转换呢!
      

  3.   

    ultrared(红色警报) :
     要操作的表已在别的字段是作了范围分区(Range Partition),在每个分区中再根据另一字段作hash subpartition.  但删除与查询语句的条件子句中,均不带分区关键字.
     我的问题关键不是慢,我通过select count(id) from tb_name where f_a=xxx and f_b=yyy; 查询50万条记录很快的.   问题在于无法做删除,同一个回滚段RBS1 持续增长到
    甚至10G,以致撑暴了回滚表空间. 根据计算,50万条记录连带所有相关的索引,总共占用的
    Oracle Block 大小不会超过2GB的.     有哪位大哥有类似删除大指的经验吗?
      

  4.   

    basically I think the way you are using is good , but anyway let me to do some studys on this case and reply you later ( if I can :-)
      

  5.   

    After beging scolded by the expert , I realize this might be what you want :-)1. Never Delete inside the Cursor , This might be the reason why it takes so much resources . Use SQL Statement like 'DELETE XXX WHERE XXXX'2. To narrow down the usage of the rollback , U can use our lovely ROWNUM :delete from tb_name where f_a=xxx and f_b=yyy
    and rownum <= 10001;
    commit; In fact , I am still confusing . But anyway please try and feedback us whether the  result is getting better .
      

  6.   

    大家看看这样行得通吗?
    1。
    我觉得楼主的V_Cur 很大,
    而且每条都要delete from tb_name where id=v_id;
    这样是不是要扫描50万*50万遍?
    2。
    if v_counter>=10000 then     --10000条提交一次
                 commit;
    v_counter := 0;
    v_counter 一直都为0或1,
    哈哈     所以回退段不够用。declare 
      i integer;
    begin
      
      loop  
        execute immediate 'delete from tb_name f_a=xxx and f_b=yyy,romnum<5000';
        commit;
        select count(*) into i from tb_name f_a=xxx and f_b=yyy;
        exit when i=0;
      end loop;
       
    end;
      

  7.   

    declare 
      i integer;
    begin
      
      loop  
        execute immediate 'delete from tb_name f_a=xxx and f_b=yyy and romnum<5000';
        commit;
        select count(*) into i from tb_name f_a=xxx and f_b=yyy;
        exit when i=0;
      end loop;
       
    end;
      

  8.   

    : black_snail(●龙飞虎○)  先说了啊。呵呵。
      

  9.   

    最后用如下脚本.效率倍增,也解决了Rollback Segment不正常增长的问题.
    我经常来csdn的,但发帖子问问题还是第一次,不蛮懂规矩,只给了5分,望各位包涵.
    特别谢谢龙飞虎、一品黄山! #!/bin/sh
    svrmgrl << EOF
    connect username/password;
    alter table tb_name nologging;
    alter session enable parallel dml;
    begin
      for i in 1..100 
      loop
        delete/*+parallel(tb_name,4)*/ from tb_name where f_a=xxx and f_b=yyy and rownum<=5000;
        commit;
      end loop;
    end;
    /
    alter session disable parallel dml;
    disconnect
    exit
    EOF