在三种方法中,笔者比较推荐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;