【oracle】使用DBMS_PARALLEL_EXECUTE并行更新表

在11.2 版本中使用DBMS_PARALLEL_EXECUTE包批量并行递增式的更新表。

1 把数据集分割成小的块

2 在每一个块上以并行的方式应用update语句,在每个块执行完成后,提交!

此更新技术有如下好处:

1 在执行update的时候,仅仅锁住一个shunk而非锁住整个表!

2 因为每个chunk 执行完毕就提交,所以当update操作失败后,之前变更的并不会回滚!

3 减小回滚空间的使用

4 提高性能

DBMS_PARALLEL_EXECUTE 使用三种方法来将一个表的数据分割成chunk

CREATE_CHUNKS_BY_NUMBER_COL : 通过指定的字段来切割表

CREATE_CHUNKS_BY_ROWID : 通过ROWID来切割表

CREATE_CHUNKS_BY_SQL : 通过用户提供的sql语句来切割表

前期准备:

使用上述功能的用户必须拥有CREATE JOB 权限,执行DBMS_SQL的权限,因为CHUNK_BY_SQL, RUN_TASK, 和RESUME_TASK 

conn /as sysdba

GRANT Create Session, Resource to yang identified by yang; 

GRANT CREATE JOB TO yang;

YANG@yangdb-rac3> INSERT /*+ APPEND */ INTO yangtab

  2  SELECT level,

  3  'Description for ' || level,

  4  CASE

  5  WHEN MOD(level, 5) = 0 THEN 10

  6  WHEN MOD(level, 3) = 0 THEN 20

  7  ELSE 30

  8  END

  9  FROM dual

 10  CONNECT BY level <= 500000;

500000 rows created.

YANG@yangdb-rac3> 

YANG@yangdb-rac3> commit;

Commit complete.      

YANG@yangdb-rac3> SELECT num_col, COUNT(*) FROM yangtab

  2  GROUP BY num_col

  3  ORDER BY num_col;

   NUM_COL   COUNT(*)

---------- ----------

        10     100000

        20     133333

        30     266667

        

1. 使用 CREATE_CHUNKS_BY_ROWID

BEGIN

DBMS_PARALLEL_EXECUTE.DROP_TASK ('test_task');

END;

/

YANG@yangdb-rac3> DECLARE

  2    l_task VARCHAR2(30) := 'test_task';

  3    l_sql_stmt VARCHAR2(32767);

  4    l_try NUMBER;

  5    l_status NUMBER;

  6  BEGIN

  7  -- Create the TASK

  8    DBMS_PARALLEL_EXECUTE.create_task (task_name => l_task);

  9  

 10  -- Chunk the table by the ROWID

 11    DBMS_PARALLEL_EXECUTE.create_chunks_by_rowid(task_name => l_task,

 12     table_owner => 'YANG',

 13     table_name => 'YANGTAB',

 14     by_row => TRUE,

 15     chunk_size => 10000);

 16  -- DML to be execute in parallel

 17     l_sql_stmt := 'UPDATE /*+ ROWID (dda) */ yangtab t SET t.num_col = t.num_col + 10 WHERE rowid BETWEEN :start_id AND :end_id';

 18  -- Run the task

 19   DBMS_PARALLEL_EXECUTE.run_task(task_name => l_task,

 20     sql_stmt => l_sql_stmt,

 21     language_flag => DBMS_SQL.NATIVE,

 22     parallel_level => 10);

 23  

 24  -- If there is error, RESUME it for at most 2 times.

 25    l_try := 0;

 26    l_status := DBMS_PARALLEL_EXECUTE.task_status(l_task);

 27    WHILE(l_try < 2 and l_status != DBMS_PARALLEL_EXECUTE.FINISHED) 

 28    Loop

 29     l_try := l_try + 1;

 30     DBMS_PARALLEL_EXECUTE.resume_task(l_task);

 31     l_status := DBMS_PARALLEL_EXECUTE.task_status(l_task);

 32    END LOOP;

 33  -- Done with processing; drop the task

 34    DBMS_PARALLEL_EXECUTE.drop_task(l_task);

 35  END;

 36  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:26.27

YANG@yangdb-rac3> SELECT num_col, COUNT(*)

  2  FROM yangtab

  3  GROUP BY num_col

  4  ORDER BY num_col; 

   NUM_COL   COUNT(*)

---------- ----------

        20     100000

        30     133333

        40     266667

2. 使用 CREATE_CHUNKS_BY_NUMBER_COL

YANG@yangdb-rac3> CREATE OR REPLACE PROCEDURE process_update (p_start_id IN NUMBER, p_end_id IN NUMBER) AS

  2    BEGIN

  3      UPDATE /*+ ROWID (dda) */ yangtab t 

  4        SET t.num_col = t.num_col + 10

  5        WHERE id BETWEEN p_start_id AND p_end_id;

  6    END;

  7  /

Procedure created.

YANG@yangdb-rac3> DECLARE

  2    l_task VARCHAR2(30) := 'test_task';

  3    l_sql_stmt VARCHAR2(32767);

  4    l_try NUMBER;

  5    l_status NUMBER;

  6  BEGIN

  7  -- Create the TASK

  8    DBMS_PARALLEL_EXECUTE.create_task (task_name => l_task);

  9  

 10  -- Chunk the table by the ROWID

 11    DBMS_PARALLEL_EXECUTE.create_chunks_by_rowid(task_name => l_task,

 12     table_owner => 'YANG',

 13     table_name => 'YANGTAB',

 14     by_row => TRUE,

 15     chunk_size => 10000);

 16  -- DML to be execute in parallel

 17     l_sql_stmt := 'UPDATE /*+ ROWID (dda) */ yangtab t SET t.num_col = t.num_col + 10 WHERE rowid BETWEEN :start_id AND :end_id';

 18  -- Run the task

 19   DBMS_PARALLEL_EXECUTE.run_task(task_name => l_task,

 20     sql_stmt => l_sql_stmt,

 21     language_flag => DBMS_SQL.NATIVE,

 22     parallel_level => 10);

 23  

 24  -- If there is error, RESUME it for at most 2 times.

 25    l_try := 0;

 26    l_status := DBMS_PARALLEL_EXECUTE.task_status(l_task);

 27    WHILE(l_try < 2 and l_status != DBMS_PARALLEL_EXECUTE.FINISHED) 

 28    Loop

 29     l_try := l_try + 1;

 30     DBMS_PARALLEL_EXECUTE.resume_task(l_task);

 31     l_status := DBMS_PARALLEL_EXECUTE.task_status(l_task);

 32    END LOOP;

 33  -- Done with processing; drop the task

 34    DBMS_PARALLEL_EXECUTE.drop_task(l_task);

 35  END;

 36  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:10.18

YANG@yangdb-rac3> SELECT num_col, COUNT(*)

  2  FROM yangtab

  3  GROUP BY num_col

  4  ORDER BY num_col; 

   NUM_COL   COUNT(*)

---------- ----------

        30     100000

        40     133333

        50     266667

Elapsed: 00:00:00.12

3. 使用 CREATE_CHUNKS_BY_SQL.

BEGIN

DBMS_PARALLEL_EXECUTE.DROP_TASK ('test_task');

END;

/

YANG@yangdb-rac3> DECLARE

2   l_chunk_sql VARCHAR2(1000);

3   l_sql_stmt VARCHAR2(1000);

4   l_try NUMBER;

5   l_status NUMBER;

6  BEGIN

7-- Create the TASK

8  DBMS_PARALLEL_EXECUTE.CREATE_TASK ('test_task');

9-- Chunk the table by NUM_COL

10  l_chunk_sql := 'SELECT DISTINCT num_col, num_col FROM yangtab';

11  DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_SQL('test_task', l_chunk_sql, false);

12-- Execute the DML in parallel

13-- the WHERE clause contain a condition on num_col, which is the chunk

14-- column. In this case, grouping rows is by num_col.

15  l_sql_stmt := 'UPDATE /*+ ROWID (dda) */ yangtab t SET t.num_col = t.num_col + 10 WHERE num_col BETWEEN :start_id AND :end_id';

16  DBMS_PARALLEL_EXECUTE.RUN_TASK('test_task', l_sql_stmt, DBMS_SQL.NATIVE,

17  parallel_level => 10);

18-- If there is error, RESUME it for at most 2 times.

19 L_try := 0;

20 L_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('test_task');

21 WHILE(l_try < 2 and L_status != DBMS_PARALLEL_EXECUTE.FINISHED) 

22 Loop

23   L_try := l_try + 1;

24   DBMS_PARALLEL_EXECUTE.RESUME_TASK('test_task');

25   L_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('test_task');

26 END LOOP;

27-- Done with processing; drop the task

28 DBMS_PARALLEL_EXECUTE.DROP_TASK('test_task');

29 end;

30 /

PL/SQL procedure successfully completed.

YANG@yangdb-rac3> SELECT num_col, COUNT(*)

  2  FROM yangtab

  3  GROUP BY num_col

  4  ORDER BY num_col; 

   NUM_COL   COUNT(*)

---------- ----------

        42     100000

        52     133333

        62     266667

时间: 2024-09-09 09:00:21

【oracle】使用DBMS_PARALLEL_EXECUTE并行更新表的相关文章

想用c#做一个小程序。要把oracle数据库里的某个表的昨日更新内容导出到xml中

问题描述 想用c#做一个小程序.要把oracle数据库里的某个表的昨日更新内容导出到xml中,现在还没点头绪,求大神指点 解决方案 解决方案二:数据库中的表增加两个字段"最后更新时间""最后更新人",然后就行了啊解决方案三:引用1楼xxoo2007的回复: 数据库中的表增加两个字段"最后更新时间""最后更新人",然后就行了啊 重要的不是数据库里面的操作.我是想用c#做个小程序,吧数据库里的表自动导成xml文件解决方案四:其实就

在Oracle数据库中同时更新两张表的简单方法_oracle

以前只会写一些简单的updaet语句,比如updae table set c1='XXX' 之类的 今天遇到一个数据订正的问题,项目背景如下,有个表A,有两个字段a1,a2还有一个关联表B,其中也有两个字段,b1和b2.其中a2和b2是关联的,想把A中的字段a1更新成B中的b1 理论上sql应该挺好写的,但是在oralce中实现了半天一直报语法错误.而且确实还有些小小细节没有注意到. 首先上测试数据 表1,ZZ_TEST1 表2,ZZ_TEST2 要把表一的text更新成表二的text1值,对应

如何在Oracle中使用临时表解决表冲突

本文介绍一个Oracle里面使用临时表解决表冲突的例子,并附创建临时表的例子 平台:windows 2000 server sp3 数据库:Oracle 9.0.1.1.1 现场描述:用户抱怨不能同时对多个单位进行数据处理,执行出现的错误信息为: SQL> exec sp_hyb_da_ryxx_dwbh_test('331028') BEGIN sp_hyb_da_ryxx_dwbh_test('331028'); END; *ERROR 位于第 1 行: ORA-02055: 分布式更新操作

Oracle中的并行

Oracle中的并行 一Oracle中的并行 首先Oracle会创建一个进程用于协调并行服务进程之间的信息传递这个协调进程将需要操作的数据集例如表的数据块分割成很多部分称为并行处理单元然后并行协调进程给每个并行进程分配一个数据单元.例如有四个并行服务进程它们就会同时处理各自分配的单元当一个并行服务进程处理完毕后协调进程就会给它们分配另外的单元如此反复直到表上的数据都处理完毕最后协调进程负责将每个小的集合合并为一个大集合作为最终的执行结果返回给用户.并行处理的机制实际上就是把一个要扫描的数据集分成

oracle中用Create Table创建表时,Storage中参数的含义!

oracle|创建 可用于:表空间.回滚段.表.索引.分区.快照.快照日志 参数名称缺省值最小值最大值说明INITIAL5(数据块)2(数据块)操作系统限定分配给Segment的第一个Extent的大小,以字节为单位,这个参数不能在alter语句中改变,如果指定的值小于最小值,则按最小值创建.NEXT5(数据块)1(数据块)操作系统限定第二个Extent的大小等于NEXT的初值,以后的NEXT值=前一NEXT大小乘以(1+PCTINCREASE/100),如果指定的值小于最小值,则按最小值创建.

Oracle并行操作之并行查询实例解析_oracle

Oracle数据库的并行操作特性,其本质上就是强行榨取除数据库服务器空闲资源(主要是CPU资源),对一些高负荷大数据量数据进行分治处理.并行操作是一种非确定性的优化策略,在选择的时候需要小心对待.目前,使用并行操作特性的主要有下面几个方面: Parallel Query:并行查询,使用多个操作系统级别的Server Process来同时完成一个SQL查询: Parallel DML:并行DML操作.类似于Parallel Query.当要对大数据量表进行DML操作,如insert.update和

Oracle的簇与簇表

Oracle的簇与簇表 --======================================== -- 簇表及簇表管理(Index clustered tables) --========================================       簇表是Oracle中一种可选.的存储表数据的方法.使用簇表可以减少磁盘I/O,改善访问簇表的联结所带来的资源开销,本文讲述了簇表的原理.创建以及管理簇表等.   一.什么是簇表及簇表的特性     1.簇表        

命令行中使用oracle命令创建数据库和表空间

本文详细介绍命令行中使用oracle命令创建数据库和表空间 1.使用超级用户登录sqlplus. 2.创建表空间: SQL> create tablespace test 2 datafile 'D:\oracle\oradata\test\test.dbf' 3 size 100M autoextend on next 10M maxsize unlimited extent management local; 3.创建用户和密码: SQL> create user Username ide

Oracle学习(一)表空间和区

1.表空间:表空间是数据库的逻辑划分,一个表空间只属于一个数据库.每个表空间由一个或多个 数据文件组成. 表空间中其他逻辑结构的数据存储在这些数据文件中.在Oracle安装完成后,会自动建立多个表空间 , 主要有: (1)System表空间:该表空间用于存放Oracle系统内部表和数据字典的数据,如表名.列名.用户 名等. (2)undo表空间:该表空间是存储撤销信息的表空间.当用户对数据库表进行修改(insert, update,delete)时, Oracle会自动使用undo表空间来临时存