05.11.2015 Views

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

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

CHAPTER 14 ■ PARALLEL EXECUTION 641<br />

3 ( user, 'T1', numrows=>10000000,numblks=>100000 );<br />

4 end;<br />

5 /<br />

PL/SQL procedure successfully completed.<br />

ops$tkyte-ORA10G> create table t2<br />

2 as<br />

3 select t1.*, 0 session_id<br />

4 from t1<br />

5 where 1=0;<br />

Table created.<br />

We used DBMS_STATS to “trick” the optimizer into thinking that there are 10,000,000 rows in<br />

that input table <strong>and</strong> that it consumes 100,000 database blocks. We want to simulate a big table<br />

here. The second table, T2, is simply a copy of the first table’s structure with the addition of a<br />

SESSION_ID column. That column will be useful to actually “see” the parallelism that takes<br />

place.<br />

Next, we need to set up object types for our pipelined function to return. The object type<br />

is simply a structural definition of the “output” of the procedure we are converting. In this<br />

case, it looks just like T2:<br />

ops$tkyte-ORA10G> CREATE OR REPLACE TYPE t2_type<br />

2 AS OBJECT (<br />

3 id number,<br />

4 text varchar2(30),<br />

5 session_id number<br />

6 )<br />

7 /<br />

Type created.<br />

ops$tkyte-ORA10G> create or replace type t2_tab_type<br />

2 as table of t2_type<br />

3 /<br />

Type created.<br />

And now for the pipelined function, which is simply the original PROCESS_DATA procedure<br />

rewritten. The procedure is now a function that produces rows. It accepts as an input the data<br />

to process in a ref cursor. The function returns a T2_TAB_TYPE, the type we just created. It is a<br />

pipelined function that is PARALLEL_ENABLED. The partition clause we are using says to <strong>Oracle</strong>,<br />

“Partition, or slice up, the data by any means that work best. We don’t need to make any<br />

assumptions about the order of the data.”<br />

You may also use hash or range partitioning on a specific column in the ref cursor. That<br />

would involve using a strongly typed ref cursor, so the compiler knows what columns are<br />

available. Hash partitioning would just send equal rows to each parallel execution server to<br />

process based on a hash of the column supplied. Range partitioning would send nonoverlapping<br />

ranges of data to each parallel execution server, based on the partitioning key. For<br />

example, if you range partitioned on ID, each parallel execution server might get ranges<br />

1. . .1000, 1001. . .20000, 20001. . .30000, <strong>and</strong> so on (ID values in that range).

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

Saved successfully!

Ooh no, something went wrong!