Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
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
- Page 640 and 641: CHAPTER 13 ■ PARTITIONING 595 Now
- Page 642 and 643: CHAPTER 13 ■ PARTITIONING 597 the
- Page 644 and 645: CHAPTER 13 ■ PARTITIONING 599 imp
- Page 646 and 647: CHAPTER 13 ■ PARTITIONING 601 OLT
- Page 648 and 649: CHAPTER 13 ■ PARTITIONING 603 5 s
- Page 650 and 651: CHAPTER 13 ■ PARTITIONING 605 Sur
- Page 652 and 653: CHAPTER 13 ■ PARTITIONING 607 On
- Page 654 and 655: CHAPTER 13 ■ PARTITIONING 609 Row
- Page 656 and 657: CHAPTER 13 ■ PARTITIONING 611 So,
- Page 658 and 659: CHAPTER 13 ■ PARTITIONING 613 Aud
- Page 660 and 661: CHAPTER 14 ■ ■ ■ Parallel Exe
- Page 662 and 663: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 664 and 665: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 666 and 667: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 668 and 669: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 670 and 671: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 672 and 673: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 674 and 675: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 676 and 677: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 678 and 679: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 680 and 681: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 682 and 683: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 684 and 685: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 686 and 687: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 688 and 689: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 692 and 693: CHAPTER 14 ■ PARALLEL EXECUTION 6
- Page 694 and 695: CHAPTER 15 ■ ■ ■ Data Loading
- Page 696 and 697: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 698 and 699: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 700 and 701: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 702 and 703: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 704 and 705: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 706 and 707: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 708 and 709: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 710 and 711: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 712 and 713: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 714 and 715: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 716 and 717: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 718 and 719: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 720 and 721: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 722 and 723: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 724 and 725: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 726 and 727: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 728 and 729: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 730 and 731: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 732 and 733: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 734 and 735: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 736 and 737: CHAPTER 15 ■ DATA LOADING AND UNL
- Page 738 and 739: CHAPTER 15 ■ DATA LOADING AND UNL
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) /