Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

rekharaghuram
from rekharaghuram More from this publisher
05.11.2015 Views

CHAPTER 14 ■ PARALLEL EXECUTION 645 19 20 delete from job_parms where job = p_job; 21 commit; 22 end; 23 / Procedure created. As you can see, it is not a significant change. Most of the added code was simply to get our inputs and the rowid range to process. The only change to our logic was the addition of the predicate on lines 12 and 13. Now let’s schedule our job. We’ll use a rather complex query using analytics to divide the table. The innermost query on lines 19 through 26 breaks the data into eight groups in this case. The first sum on line 22 is computing a running total of the sum of blocks; the second sum on line 23 is the total number of blocks. If we integer divide the running total by the desired “chunk size” (the total size divided by 8 in this case), we can create groups of files/blocks that cover about the same amount of data. The query on lines 8 through 28 finds the high and low file numbers and block numbers by GRP, and returns the distinct entries. It builds the inputs we can then send to DBMS_ROWID to create the rowids Oracle wants. We take that output and, using DBMS_JOB, submit a job to process the rowid range: big_table-ORA10G> declare 2 l_job number; 3 begin 4 for x in ( 5 select dbms_rowid.rowid_create ( 1, data_object_id, lo_fno, lo_block, 0 ) min_rid, 6 dbms_rowid.rowid_create ( 1, data_object_id, hi_fno, hi_block, 10000 ) max_rid 7 from ( 8 select distinct grp, 9 first_value(relative_fno) over (partition by grp order by relative_fno, block_id 10 rows between unbounded preceding and unbounded following) lo_fno, 11 first_value(block_id ) over (partition by grp order by relative_fno, block_id 12 rows between unbounded preceding and unbounded following) lo_block, 13 last_value(relative_fno) over (partition by grp order by relative_fno, block_id 14 rows between unbounded preceding and unbounded following) hi_fno, 15 last_value(block_id+blocks-1) over (partition by grp order by relative_fno, block_id 16 rows between unbounded preceding and unbounded following) hi_block, 17 sum(blocks) over (partition by grp) sum_blocks 18 from ( 19 select relative_fno, 20 block_id, 21 blocks, 22 trunc( (sum(blocks) over (order by relative_fno, block_id)-0.01) /

646 CHAPTER 14 ■ PARALLEL EXECUTION 23 (sum(blocks) over ()/8) ) grp 24 from dba_extents 25 where segment_name = upper('BIG_TABLE') 26 and owner = user order by block_id 27 ) 28 ), 29 (select data_object_id from user_objects where object_name = upper('BIG_TABLE') ) 30 ) 31 loop 32 dbms_job.submit( l_job, 'serial(JOB);' ); 33 insert into job_parms(job, lo_rid, hi_rid) 34 values ( l_job, x.min_rid, x.max_rid ); 35 end loop; 36 end; 37 / PL/SQL procedure successfully completed. That PL/SQL block would have scheduled up to eight jobs for us (fewer if the table could not be broken in to eight pieces due to insufficient extents or size). We can see how many jobs were scheduled and what their inputs are as follows: big_table-ORA10G> select * from job_parms; JOB LO_RID HI_RID ---------- ------------------ ------------------ 172 AAAT7tAAEAAAAkpAAA AAAT7tAAEAAABQICcQ 173 AAAT7tAAEAAABQJAAA AAAT7tAAEAAABwICcQ 174 AAAT7tAAEAAABwJAAA AAAT7tAAEAAACUICcQ 175 AAAT7tAAEAAACUJAAA AAAT7tAAEAAAC0ICcQ 176 AAAT7tAAEAAAC0JAAA AAAT7tAAEAAADMICcQ 177 AAAT7tAAEAAADaJAAA AAAT7tAAEAAAD6ICcQ 178 AAAT7tAAEAAAD6JAAA AAAT7tAAEAAAEaICcQ 179 AAAT7tAAEAAAEaJAAA AAAT7tAAEAAAF4ICcQ 8 rows selected. big_table-ORA10G> commit; Commit complete. That commit released our jobs for processing. We have JOB_QUEUE_PROCESSES set to 0 in the parameter file, so all eight started running and shortly finished. The results are as follows: big_table-ORA10G> select session_id, count(*) 2 from t2 3 group by session_id; SESSION_ID COUNT(*) ---------- ---------- 172 130055

CHAPTER 14 ■ PARALLEL EXECUTION 645<br />

19<br />

20 delete from job_parms where job = p_job;<br />

21 commit;<br />

22 end;<br />

23 /<br />

Procedure created.<br />

As you can see, it is not a significant change. Most of the added code was simply to get our<br />

inputs <strong>and</strong> the rowid range to process. The only change to our logic was the addition of the<br />

predicate on lines 12 <strong>and</strong> 13.<br />

Now let’s schedule our job. We’ll use a rather complex query using analytics to divide the<br />

table. The innermost query on lines 19 through 26 breaks the data into eight groups in this<br />

case. The first sum on line 22 is computing a running total of the sum of blocks; the second<br />

sum on line 23 is the total number of blocks. If we integer divide the running total by the desired<br />

“chunk size” (the total size divided by 8 in this case), we can create groups of files/blocks that<br />

cover about the same amount of data. The query on lines 8 through 28 finds the high <strong>and</strong> low<br />

file numbers <strong>and</strong> block numbers by GRP, <strong>and</strong> returns the distinct entries. It builds the inputs<br />

we can then send to DBMS_ROWID to create the rowids <strong>Oracle</strong> wants. We take that output <strong>and</strong>,<br />

using DBMS_JOB, submit a job to process the rowid range:<br />

big_table-ORA10G> declare<br />

2 l_job number;<br />

3 begin<br />

4 for x in (<br />

5 select dbms_rowid.rowid_create<br />

( 1, data_object_id, lo_fno, lo_block, 0 ) min_rid,<br />

6 dbms_rowid.rowid_create<br />

( 1, data_object_id, hi_fno, hi_block, 10000 ) max_rid<br />

7 from (<br />

8 select distinct grp,<br />

9 first_value(relative_fno)<br />

over (partition by grp order by relative_fno, block_id<br />

10 rows between unbounded preceding <strong>and</strong> unbounded following) lo_fno,<br />

11 first_value(block_id )<br />

over (partition by grp order by relative_fno, block_id<br />

12 rows between unbounded preceding <strong>and</strong> unbounded following) lo_block,<br />

13 last_value(relative_fno)<br />

over (partition by grp order by relative_fno, block_id<br />

14 rows between unbounded preceding <strong>and</strong> unbounded following) hi_fno,<br />

15 last_value(block_id+blocks-1)<br />

over (partition by grp order by relative_fno, block_id<br />

16 rows between unbounded preceding <strong>and</strong> unbounded following) hi_block,<br />

17 sum(blocks) over (partition by grp) sum_blocks<br />

18 from (<br />

19 select relative_fno,<br />

20 block_id,<br />

21 blocks,<br />

22 trunc( (sum(blocks) over (order by relative_fno, block_id)-0.01) /

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!