【oracle】使用DBMS_PARALLEL_EXECUTE并行更新表

简介: 在11.2 版本中使用DBMS_PARALLEL_EXECUTE包批量并行递增式的更新表。1 把数据集分割成小的块2 在每一个块上以并行的方式应用update语句,在每个块执行完成后,提交!此更新技术有如下好处:1 在执行update的时候,仅仅锁住一个...
在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 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
 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
 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
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

目录
相关文章
|
SQL 存储 负载均衡
《Parallel SQL Execution in Oracle 10g》 论文解读
《Parallel SQL Execution in Oracle 10g》 论文解读
《Parallel SQL Execution in Oracle 10g》 论文解读
|
SQL 负载均衡 并行计算
Parallel SQL Execution in Oracle 10g 论文解读
这篇简短的paper从非常high level的角度描述了下Oracle 10g对于parallel query所做的重新设计和其中的一些优化,由于Oracle RAC特殊的share-disk架构,使其在并行计算上与普通的MPP数据库有一些不同,例如对于worker的调度和分配方式以及对于资源/数据的动态调整。
223 0
Parallel SQL Execution in Oracle 10g 论文解读
|
SQL Oracle 关系型数据库
ORACLE的SQL JOIN方式小结
在ORACLE数据库中,表与表之间的SQL JOIN方式有多种(不仅表与表,还可以表与视图、物化视图等联结),官方的解释如下所示   A join is a query that combines rows from two or more tables, views, or materialized views.
1214 0

热门文章

最新文章

推荐镜像

更多