Here is another illustration of some of the powerful capabilities of the DBMS_PARALLEL_EXECUTE package in the Oracle database, carrying on from the earlier post here. One of the comments from that post was on how to insert into a different named table within each chunk and that insert can perform parallel DML also. This kind of scenario could be interesting for very high end processing, it could be end point target tables or tables that are prepared and then you perform partition exchanges with them or something.
The image below shows a variation on the original post where rather than inserting into a specific partition, you write into a specific table.
Driving the whole process can be your own chunking criteria, the question was how to drive this process from a table using SQL such as ‘select distinct level_key, level_key from chunk_table’ where chunk_table has the level_key and the target table name. For example it could contain the following data;
level_key | table_name |
1 | sales_level1 |
2 | sales_level2 |
3 | sales_level3 |
4 | sales_level4 |
… |
So the first chunk with level_key 1 will write the results to table sales_level1 etc.
You can use the DBMS_PARALLEL_PACKAGE as follows to create this functionality. The start/end values have to be of data type NUMBER, so you will have to lookup the (target) table name inside your PLSQL block within the statement provided in the run_task call.
This block has the query to determine the chunks .....
begin
begin
DBMS_PARALLEL_EXECUTE.DROP_TASK(task_name => 'TASK_NAME');
exception when others then null;
end;
DBMS_PARALLEL_EXECUTE.CREATE_TASK(task_name => 'TASK_NAME');
DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_SQL(task_name => 'TASK_NAME',
sql_stmt =>'select distinct level_key, level_key from chunk_table', by_rowid => false);
end;
Then the next block will construct the and process the tasks......
begin
DBMS_PARALLEL_EXECUTE.RUN_TASK (task_name => 'TASK_NAME',
sql_stmt =>'declare
s varchar2(16000); vstart_id number := :start_id; vend_id number:= :end_id;
table_name varchar2(30);
begin
select table_name into table_name from chunk_table where level_key=vstart_id;
s:=''insert into ''||table_name||'' select /*+ PARALLEL(STG, 8) */ colx from STAGING_TABLE STG
where level_key =:vstart_id'';
execute immediate s using vstart_id;
commit;
end;',
language_flag => DBMS_SQL.NATIVE, parallel_level => 2 );
end;
The anonymous PLSQL block can be any arbitrary code, you can see the table name of the target is retrieved, the example does a parallel INSERT using the hint PARALLEL(STG,8). Anyway, good to share.