生产上要修改某个产品的产品代号, 而我们系统是以产品为中心的, 牵一发而动全身, 涉及表几乎覆盖全部, 有些表数据量是相当大的, 达到千万, 亿级别.

单纯的维护产品代号的 SQL 是不难的, 但是性能是最大的问题, 最后采用了 rowid+forall分批更新策略.

细节涉及:

游标(rowid)

dbms_sql.Urowid_Table

(异常声明;)

fetch v_rowid_cursor bulk collect into v_rowid_table limit v_once_commit; ...

forall i in 1 .. v_rowid_table.count save exceptions ...

完整代码:

PL/SQL存储过程分批更新↓

 --rowid+forall批量更新
declare
v_total_count integer default 500000; --待更新目标记录总计
v_once_commit integer default 10000; --单次提交量
v_pre_prod_code char(8) := '';
v_new_prod_code char(8) := '9031000X';
v_dml_name varchar2(100) := 'update tb_cust_vol_list 20181215 01';
v_suc_count integer := 0; --成功提交计数
v_err_count integer := 0; --失败记录数
v_curr_batch integer := 0; --当前提交批次
v_start_time date := sysdate; --开始时间
--待更新目标记录rowids
cursor v_rowid_cursor is
select rowid from tb_cust_vol_list
where prod_code = v_pre_prod_code
order by rowid; --rowid排序,提高效率
v_rowid_table dbms_sql.Uv_rowid_table; --临时单次rowid放置表
v_error exception; --异常声明
pragma exception_init(v_error, -24381); --指定ora-错误码 begin
--操作日志
insert into tb_dml_log values (
v_dml_name,
v_total_count,
v_once_commit,
v_start_time,
v_start_time,
0, 0, 0, 0, 0
);
commit; open v_rowid_cursor; --打开rowids游标
loop
exit when v_rowid_cursor%notfound;
--临时rowids表
fetch v_rowid_cursor bulk collect into v_rowid_table limit v_once_commit;
exit when v_rowid_table.count = 0; begin
forall i in 1 .. v_rowid_table.count save exceptions
--rowid定位行更新
update tb_cust_vol_list set prod_code=v_new_prod_code where rowid=v_rowid_table(i);
exception
when v_error then --目标异常
dbms_output.put_line('ora-24381, error in array DML !');
dbms_output.put_line('exception count: ' || sql%bulk_exceptions.count);
v_err_count := v_err_count + sql%bulk_exceptions.count;
when others then
dbms_output.put_line('ora-XXX error occurred !');
dbms_output.put_line('exception count: ' || sql%bulk_exceptions.count);
v_err_count := v_err_count + sql%bulk_exceptions.count;
end; v_suc_count := v_suc_count + v_rowid_table.count;
v_curr_batch := v_curr_batch + 1;
--更新log
update tb_dml_log a set
a.curr_time=sysdate,
a.curr_cost=ceil((sysdate-v_start_time)*24*60*60),
a.curr_batch=v_curr_batch,
a.process=v_suc_count/a.total_count,
a.suc_count=v_suc_count,
a.err_count=v_err_count
where a.dml_name=v_dml_name;
commit; end loop; dbms_output.put_line('total error count: ' || v_err_count);
end;

有帮助的博客:
https://blog.csdn.net/leinuo180/article/details/23344647

其他考虑:

如果有的表目标数据实在太大, 就算上述优化依然很费时间, 可将此表的目标数据拆分, 比如按月, 按编号.. 分几个脚本, 维护时并行执行.

查询语句获取所有目标数据的 rowid 时, 如果占比很大(索引空间大), 可以尝试禁用索引查询, 使用全表并行查(网上看到的,本人还未尝试).

超大表要注意索引空间的维护.

@20190126更新

批量数据更新方式

1)表重建

即先新建复制表(create 新表(...) as select ... from 旧表 where ...),然后删除旧表(drop),最后修改表名(rename 新表名 to 旧表名),最后恢复表结构(约束,索引等)。

2)rowid+forall PL/SQL存储过程更新

即上面的办法

3)JDBC程序分批更新

优点是DB无关性,性能也不慢,只是数据量太大(千万级)时,力不从心。

Oracle大量数据更新策略的更多相关文章

  1. ASP.NET Cache 实现依赖Oracle的缓存策略

    ASP.NET 中的缓存提供了对SQL依赖项的支持,也就是说当SQL SERVER数据库中的表或行中的数据被更改后,缓存中的页面就失效,否则,页面输出可一直保留在缓存当中.这确实为程序员提供了方便.但 ...

  2. Oracle RMAN备份策略

    建立增量备份:如果数据库运行于不归档模式下,只能在数据库干净关闭的情况下 ( 以 normal .immediate . transactional 方式关闭 ) 才能进行一致性的增量备份,如果数据库 ...

  3. Oracle数据库备份策略:全备与增量备份

    一.RMAN全备份 在数据量比较小.或者数据库服务器性能很强大的情况下,可以每天进行一次全备份. 全被策略如下 1.crontab定时任务,避开业务繁忙时段 ##################### ...

  4. Web系统与自控系统数据通讯架构 之 OPC DA DataChangeEventHandler 非热点数据更新策略 ,

    在使用OPC 采集 工控数据时,在DA模式下.采集数据通常用到 DataChangeEventHandler这个事件.但有时会遇到一些问题,就是当数据不变化时时不会触发 DataChange 这个事件 ...

  5. Oracle的Recyclebin策略

    1.从oracle10g开始删除数据库表的时候并不是真正删除,而是放到了recyclebin中,这个过程类似 windows里面删除的文件会被临时放到回收站中. 2.删除的表系统会自动给他重命名就是你 ...

  6. Oracle备份及备份策略

    第二章. 了解备份的重要性 可以说,从计算机系统出世的那天起,就有了备份这个概念,计算机以其强大的速度处理能力,取代了很多人为的工作,但是,往往很多时候,它又是那么弱不禁风,主板上的芯片.主板电路.内 ...

  7. oracle与DB2

    1.体系结构,DB2的实例和数据库分开的做法,我个人还是比较喜欢的,因为实例可以创建多个,数据库的恢复直接恢复到实例下就可以了,相对ORACLE简单多了. 2.管理工具,DB2的管理工具做得太简陋了, ...

  8. DB2和Oracle区别

    转 http://blog.chinaunix.net/uid-7374279-id-2057574.html 写在前面:今天客户来访(日本人),问我DB2和Oracle区别.因为不是DBA(勉强的理 ...

  9. 微軟将从 .NET 4 以后的版本弃用 System.Data.OracleClient 以及Oracle 的各种连接方法

    这是微软官方 ADO.NET Team Blog 去年就公布的消息: http://blogs.msdn.com/adonet/archive/2009/06/15/system-data-oracl ...

随机推荐

  1. PointCloud及其经典论文介绍

    这篇博客会介绍点云的基本知识,重点介绍最近两年发表的部分经典论文,有什么建议欢迎留言! 点云基本介绍 点云是某个坐标系下的点的数据集,包含了丰富的信息,可以是三维坐标X,Y,Z.颜色.强度值.时间等等 ...

  2. 逆向MFC程序

    目录 @ 1 MFC执行流程 1.1 环境支持 1.2 分析 1.3 实践探索 1.3.1 创建一个MFC程序 1.3.2 下关键断点并调试 1.4 转向MFC库源文件中观测 2 逆向 2.1 特征码 ...

  3. Cookie和Session的使用详解

    我们在使用接口请求时经常听到Cookie和Session的知识,那么它们的实际意义和使用场景在哪里呢 ?    介绍如下 一.首先需要了解的是为什么需要有Cookie和Session这两个东西:Htt ...

  4. String常量池和intern方法

    String s1 = "Hello"; String s2 = "Hello"; String s3 = "Hel" + "lo ...

  5. 当下最流行的微服务与spring cloud,你搞清楚了吗?

    微服务架构:Spring-Cloud 什么是微服务? 微服务就是把原本臃肿的一个项目的所有模块拆分开来并做到互相没有关联,甚至可以不使用同一个数据库. 比 如:项目里面有User模块和Power模块, ...

  6. IDED中配置SVN没有svn.exe解决办法

    首先在idea中配置svn时

  7. python3学习-pickle模块

    pickle提供了一个简单的持久化功能.可以将对象以文件的形式存放在磁盘上. 基本接口: pickle.dump(obj, file, [,protocol]) 注解:将对象obj保存到文件file中 ...

  8. 多态、继承、this、super

    先放一下多态的定义: (360词典上的哈) 多态(Polymorphism)按字面的意思就是"多种状态".在面向对象语言中,接口的多种不同的实现方式即为多态.引用Charlie C ...

  9. 分享我的GD32F450的IAP过程

    最近一个项目使用GD32F450VI+ESP8266需要做远程升级,基本参考正点原子IAP的那一章节,但是在GD32F450上却遇到了问题,无法跳转,然后使用正点原子的开发板stm32f429,以及s ...

  10. Java——集合类

    1.容器的打印 import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import jav ...