【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
相关文章
|
Oracle 关系型数据库 数据库
Oracle查询优化-复制表的定义及数据
【1月更文挑战第5天】【1月更文挑战第14篇】在Oracle数据库中,复制表定义和复制表数据是两个常见的操作。
232 1
|
SQL 监控 Oracle
关系型数据库Oracle并行执行
【7月更文挑战第12天】
325 14
|
消息中间件 关系型数据库 Kafka
实时计算 Flink版产品使用合集之oracle cdc 抽取新增一张表 可以从savepoint恢复吗
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
117 0
|
SQL Oracle 关系型数据库
关系型数据库Oracle并行查询
【7月更文挑战第12天】
345 15
|
Oracle 关系型数据库 数据处理
|
SQL 监控 Oracle
|
SQL 监控 Oracle
|
SQL Oracle 关系型数据库
实时计算 Flink版产品使用问题之oracle无主键的表支持同步吗如何实现
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
运维 DataWorks Oracle
DataWorks产品使用合集之在标准模式下,当同步Oracle的表或视图时,是否需要在源端的测试和生产环境中都存在要同步的表或视图
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
125 3
|
资源调度 Oracle 关系型数据库
实时计算 Flink版产品使用合集之同步Oracle数据时,一张表产生了大量的连接数,如何处理
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。