execute执行并行更新(2)

在三种方法中,笔者比较推荐rowid方法,理由是条件要求低、操作速度快。如果操作过程中没有明确的对数据表作业,这种策略是首选。具体比较可以从下面的实验中看出。

确定了划分方法,还要确定每个chunk的大小。注意:这个chunk设置大小并不一定是每个chunk操作数据行的数量。针对不同的分区类型,有不同的策略。这个在下面实验中笔者也会给出明确的解析。
 
并行进程个数表示的是当“一块”任务被划分为“一堆”相互独立的任务集合之后,准备多少个工作进程进行工作。这个是并行包使用的关键,类似于并行度,是需要依据实际软硬件资源负载情况综合考虑。
 
长时间作业存在一个问题,就是调用用户希望随时了解执行情况。Oracle提供了两个数据视图user_parallel_execute_tasks和user_parallel_execute_chunks,分别查看Task执行情况和各个chunk执行完成情况。
 
在Oracle官方文档中,给出了调用dbms_parallel_execute包的方法流程,本文使用的也就是这个脚本的变种,特此说明。下面,我们先看第一种by rowid方法。
 
 

3、By Rowid划分chunk方法

Oracle中的rowid是数据实际物理位置的表示。借助rowid直接定位数据,是目前Oracle获取数据最快的方法。所以在RBO中,第一执行计划被确定为rowid访问方式。
 
依据Oracle文档提供的PL/SQL匿名块,修改处我们第一个rowid范围查询。

declare

vc_task varchar2(100);

vc_sql varchar2(1000);

n_try number;

n_status number;

begin

--Define the Task

vc_task := 'Task 1: By Rowid';  --Task名称

dbms_parallel_execute.create_task(task_name => vc_task); --手工定义一个Task任务;

--Define the Spilt

dbms_parallel_execute.create_chunks_by_rowid(task_name => vc_task,

table_owner => 'SYS',

table_name => 'T',

by_row => true,

chunk_size => 1000); --定义Chunk

vc_sql := 'update /*+ ROWID(dda) */t set DATA_OBJECT_ID=object_id+1 where rowid between :start_id and :end_id';
 
  --Run the task

dbms_parallel_execute.run_task(task_name => vc_task,

sql_stmt => vc_sql,

language_flag => dbms_sql.native,

parallel_level => 2); --执行任务,确定并行度

--Controller

n_try := 0;

n_status := dbms_parallel_execute.task_status(task_name => vc_task);

while (n_try<2 and n_status != dbms_parallel_execute.FINISHED) loop

dbms_parallel_execute.resume_task(task_name => vc_task);

n_status := dbms_parallel_execute.task_status(task_name => vc_task);

end loop;       

--Deal with Result

dbms_parallel_execute.drop_task(task_name => vc_task);                                   

end;

/

从调用过程来看,这个并行操作包括下面几个步骤:

ü  定义Task;

ü  确定chunk划分方法,定义每个chunk的范围信息;

ü  执行作业,确定并行作业进程数量;

这个调用过程和我们常见的并行方式有很大差异,类似于Oracle的Job Schedule机制。由于执行过程比较长,我们可以有比较从容的查看并行执行包的情况。

从user_parallel_execute_tasks中,看到当前作业的关键信��。注意:chunk_type表示的是采用什么样的划分方法。JOB_PREFIX对应的则是Schedule中的内容。
 
 

SQL> select task_name, chunk_type, JOB_PREFIX from user_parallel_execute_tasks;

TASK_NAME            CHUNK_TYPE  JOB_PREFIX

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

Task 1: By Rowid    ROWID_RANGE  TASK$_4

在user_parallel_execute_chunks中,作业的所有chunk划分,每个chunk对应的一行数据。其中包括这个chunk的起始和截止rowid。对应的chunk取值对应的就是每个chunk的数据行数。
 
 

SQL> select chunk_id, task_name, status, start_rowid, end_rowid from user_parallel_execute_chunks where rownum<10;
 
 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/b4368eb260817dc774756f6ef21b4f1e.html