Deprecated: Assigning the return value of new by reference is deprecated in /home/ostwoora/public_html/en/wp-settings.php on line 520

Deprecated: Function set_magic_quotes_runtime() is deprecated in /home/ostwoora/public_html/en/wp-settings.php on line 18
OS & Oracle
May 2012
M T W T F S S
« Apr    
 123456
78910111213
14151617181920
21222324252627
28293031  

XMLType, its storage model and index?

XMLType is an abstract type for programming, whose storage model can be unstructured storage or structure storage. 

Oracle XML DB uses XML schema as a mechanism for defining how the contents of an XMLType should be stored inside the database. Currently Oracle XML DB
provides two options:

  1. Unstructured storage. The content of the XMLType is persisted as XML text using a CLOB datatype. This option is available for non-schema-based and schema-based XML content. When the XML is to be stored and retrieved as complete documents, unstructured storage may be the best solution as it offers the fastest rates of throughput when storing and retrieving XML content.
  2. Structured storage. The content of the XMLType is persisted as a set of SQL objects. The structured storage option is only available when the XMLType table or column has been constrained to a global element defined by XML schema. If there is a need to extract or update sections of the document, perform XSL transformation on the document, or work through the DOM API, then structured storage may be the preferred storage type. Structured storage allows all these operations to take place more efficiently but at a greater overhead when storing and retrieving the entire document.

Let’s go to the index topic. This is the range of structured storage. Similar to the regular index, we can create an index when we create the table, or we can create an index using create index statement. Below is an example using create index.

CREATE INDEX ipurchaseorder_rejectedby
ON purchaseorder (extractValue(OBJECT_VALUE, '/PurchaseOrder/Reject/User'));

One limitation is that this require the element to index must occur only once, as extractValue can’t return multiple values.

If the elements occurs multiple times, the index must be create when creating the table using nested table for the index element, one such example is as below:

CREATE TABLE purchaseorder OF XMLType
XMLSCHEMA "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd"
ELEMENT "PurchaseOrder"
VARRAY "XMLDATA"."ACTIONS"."ACTION"
STORE AS TABLE action_table
((PRIMARY KEY (NESTED_TABLE_ID, SYS_NC_ARRAY_INDEX$))
ORGANIZATION INDEX OVERFLOW)
VARRAY "XMLDATA"."LINEITEMS"."LINEITEM"
STORE AS TABLE lineitem_table
((PRIMARY KEY (NESTED_TABLE_ID, SYS_NC_ARRAY_INDEX$))
ORGANIZATION INDEX OVERFLOW);

In this way, the indexes for action and lineitem is setup when creating the table.

This CREATE TABLE statement above is equivalent to the CREATE TABLE statement automatically generated by Oracle XML DB when the schema annotation storeVarrayAsTable="true" is included in the root element of the PurchaseOrder XML schema (and genTables="true" is set during schema registration). When this annotation is used, the nested tables generated by the XML schema registration process are given system-generated names, which can be difficult to work with. You can give them more meaningful names using the SQL statement RENAME TABLE.

What elementFormDefault means in XML schema?

The elementFormDefault can be qualified or unqualified, unqualified is the default.
"qualified" means that all the local elements(such as shipTo below) must be qualified, either through specified namespace or default namespace.
Example:
po.xsd as:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1"
        elementFormDefault="qualified"
        attributeFormDefault="qualified">
  <element name="purchaseOrder" type="po:PurchaseOrderType"/>
  <complexType name="PurchaseOrderType">
    <sequence>
      <element name="shipTo"    type="string"/>
    </sequence>
  </complexType>
</schema> 


Corresponding xml can be:

<?xml version="1.0"?>
<prx:purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/P01 po2.xsd"
xmlns:prx="http://www.example.com/PO1">
   <prx:shipTo >
  </prx:shipTo>
</prx:purchaseOrder> 

OR

<?xml version="1.0"?>
<purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/P01 po2.xsd"
xmlns="http://www.example.com/PO1">
   <shipTo >
  </shipTo>
</purchaseOrder> 

"unqualified" means that all the local elements mustn’t be qualified, or to say, must have no namespace.

po.xsd as:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:po="http://www.example.com/PO1"
        targetNamespace="http://www.example.com/PO1"
        elementFormDefault="unqualified"
        attributeFormDefault="unqualified">
  <element name="purchaseOrder" type="po:PurchaseOrderType"/>
  <complexType name="PurchaseOrderType">
    <sequence>
      <element name="shipTo"    type="string"/>
    </sequence>
  </complexType>
</schema> 

Corresponding xml can be:

<?xml version="1.0"?>
<purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/P01 po.xsd"
xmlns="http://www.example.com/PO1">
   <shipTo xmlns="">
  </shipTo>
</purchaseOrder> 

OR

<?xml version="1.0"?>
<prx:purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/P01 po.xsd"
xmlns:prx="http://www.example.com/PO1">
   <shipTo>
  </shipTo>
</prx:purchaseOrder>

You can test the above examples in the XML-editor, such as JDeveloper, validating the grammar automatically.

Also, the references below can be useful if you want the further understanding.

And Recently, My colleague Corey clarify this concept too in another blog, whose URL is elementFormDefault attribute, attributeFormDefault attribute and form attribute in XML Schema , also referencing to the above documents:) 

Common Causes and Solutions for ORA-1157

SQL> startup

ORACLE instance started.

Total System Global Area  202868968 bytes

Fixed Size                   731368 bytes

Variable Size             167772160 bytes

Database Buffers           33554432 bytes

Redo Buffers                 811008 bytes

Database mounted.

ORA-01157: cannot identify/lock data file 7 - see DBWR trace file

ORA-01110: data file 7: ‘/opt/oracle/product/9.2/dbs/datafile.dbf’

1. The datafile does exist, but Oracle cannot find it.

2. The datafile does not exist or unsuable by Oracle. The datafile has been physically removed or damaged to an extent that Oracle cannot recognize it anymore.

a. Recreate the tablespace that the datafile belongs to.

1. If the database is down, mount it. SVRMGR> STARTUP MOUNT PFILE=’<location_of_pfile>’;
2. Offline drop the datafile. SVRMGR> ALTER DATABASE DATAFILE ‘<full_path_file_name>’ OFFLINE DROP;
3. If the database is at mount point, open it. SVRMGR> ALTER DATABASE OPEN;
4. Drop the user tablespace. SVRMGR> DROP TABLESPACE <tablespace_name> INCLUDING CONTENTS;
Note: The users can stop with this step if they do not want the tablespace anymore in the database.
5. Recreate the tablespace. SVRMGR> CREATE TABLESPACE <tablespace_name> DATAFILE ‘<datafile_full_path_name’> SIZE <required_size>;
6. Recreate all the previously existing objects in the tablespace.

b. Recover the datafile using normal recovery procedures.

     1. Restore the lost file from a backup.  
     2. If the database is down, mount it.  
      SQL>STARTUP MOUNT PFILE=<location_of_pfile>; 
     3. Issue the following query:  
        SQL> SELECT V1.GROUP#, MEMBER, SEQUENCE#,
                FIRST_CHANGE#  
                FROM V$LOG V1, V$LOGFILE V2  
                WHERE V1.GROUP# = V2.GROUP# ;  
        This will list all your online redolog files and their respective sequence and first change numbers.   
    4. issue the query:   
          SQL> SELECT FILE#, CHANGE# FROM V$RECOVER_FILE;   
    This query will list the files needing to recover.
   5. use rman to restore and recover the datafile.

3. Operating Systems (OS) Tempfiles missing:

      When using TEMPORARY tablespaces with tempfiles, the absence of the  tempfile at the OS level can cause ORA-1157. 
      Since Oracle does not checkpoint tempfiles, the database can be opened even with missing tempfiles. 
      The solution in this case would be to drop the logical tempfile and add a new one.

For example:
     SQL>  select * from dba_objects order by object_name;
           select * from dba_objects order by object_name;
               *
     ERROR at line 1:
     ORA-01157: cannot identify/lock data file 1026 - see DBWR trace file
     ORA-01110: data file 1026: ‘/Oracle/oradata/V901/temp2_01.tmp’

     SQL> alter database tempfile ‘/Oracle/oradata/V901/temp2_01.tmp’ drop;
     SQL> select tablespace_name, file_name from dba_temp_files;
     SQL> alter tablespace temp2
          add tempfile ‘/Oracle/oradata/V901/temp2_01.tmp’ size 5m;

 

The article is mainly from metalink Note:184327.1

table data block corruption simulation

1. corrupt the data file corresponding to the table
For this purpose, a dd command is generate from the Oracle views.

set heading off
set lines 113
SELECT 'dd of=' || f.file_name || ' bs=8192 conv=notrunc seek=' ||
       to_number(S.HEADER_BLOCK + 1) || ' << EOF',
       'CORRUPT corrupt CORRUPT corrupt CORRUPT corrupt CORRUPT corrupt CORRUPT CORRUPT CORRUPT CORRUPT corrupt corrupt ',
       'EOF'
  FROM DBA_SEGMENTS S, dba_data_files f, dba_tables t
 WHERE f.tablespace_name = t.tablespace_name
   and S.SEGMENT_NAME = t.table_name
   and t.table_name = 'BTEST'
   and S.OWNER = t.owner
   and t.owner = 'SYS';

After executing this dd comand, the storage space of table sys.btest will be corrupted.

2. flush the buffer cache, so the next querying statement will read data from storage.

alter system flush buffer_cache;

3. select should be error.

sys@ORCL> select * from btest;
select * from btest
              *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 16, block # 12)
ORA-01110: data file 16: '/opt/oracle/oradata/orcl/ORCL/datafile/o1_mf_broken_2vjk5vss_.dbf'

4. After shutdown and startup, the database functions normal, but the btest will be unavailable.

How to have multiple DFO trees

DFO means "Data Flow Operator". Actually, “queries” don’t run in parallel, it’s "data flow operations" (DFOs) that run in parallel, and a single query can be made up of several data flow operations. DFO tree is composite with DFOs, usually one query have one DFO tree. such as

select /*+ parallel(t1 4) parallel(t2 4) */ rownum, t1.id from t1, t2 where t1.id = t2.id;

------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |          |   100 |   600 |     5  (20)| 00:00:01 |        |      |            |
|   1 |  COUNT                   |          |       |       |            |          |        |      |            |
|   2 |   PX COORDINATOR         |          |       |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM)   | :TQ10002 |   100 |   600 |     5  (20)| 00:00:01 |  Q1,02 | P->S | QC (RAND)  |
|*  4 |     HASH JOIN BUFFERED   |          |   100 |   600 |     5  (20)| 00:00:01 |  Q1,02 | PCWP |            |
|   5 |      PX RECEIVE          |          |   100 |   300 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
|   6 |       PX SEND HASH       | :TQ10000 |   100 |   300 |     2   (0)| 00:00:01 |  Q1,00 | P->P | HASH       |
|   7 |        PX BLOCK ITERATOR |          |   100 |   300 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   8 |         TABLE ACCESS FULL| T1       |   100 |   300 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
|   9 |      PX RECEIVE          |          |   100 |   300 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
|  10 |       PX SEND HASH       | :TQ10001 |   100 |   300 |     2   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |
|  11 |        PX BLOCK ITERATOR |          |   100 |   300 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
|  12 |         TABLE ACCESS FULL| T2       |   100 |   300 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
------------------------------------------------------------------------------------------------------------------

The result from v$pq_tqstat:

hlr@ORCL> select * from v$pq_tqstat  order by dfo_number , tq_id , server_type;

DFO_NUMBER      TQ_ID SERVER_TYPE       NUM_ROWS      BYTES  OPEN_TIME AVG_LATENCY      WAITS   TIMEOUTS PROCESS      INSTANCE
---------- ---------- --------------- ---------- ---------- ---------- ----------- ---------- ---------- ---------- ----------
         1          0 Consumer                28        192          0           0         10          1 P002                1
         1          0 Consumer                26        184          0           0          9          1 P001                1
         1          0 Consumer                19        156          0           0         10          2 P000                1
         1          0 Consumer                27        188          0           0         10          3 P003                1
         1          0 Producer                 0         80          0           0          0          0 P007                1
         1          0 Producer                 0         80          0           0          0          0 P005                1
         1          0 Producer               100        480          0           0          2          1 P004                1
         1          0 Producer                 0         80          0           0          0          0 P006                1
         1          1 Consumer                28        192          0           0         10          1 P002                1
         1          1 Consumer                26        184          0           0          9          1 P001                1
         1          1 Consumer                19        156          0           0         10          3 P000                1
         1          1 Consumer                27        188          0           0         10          2 P003                1
         1          1 Producer               100        480          0           0          1          0 P004                1
         1          1 Producer                 0         80          0           0          0          0 P007                1
         1          1 Producer                 0         80          0           0          0          0 P005                1
         1          1 Producer                 0         80          0           0          0          0 P006                1
         1          2 Consumer               100        480          0           0          0          0 QC                  1
         1          2 Producer                27        128          0           0          0          0 P003                1
         1          2 Producer                26        124          0           0          0          0 P001                1
         1          2 Producer                28        132          0           0          0          0 P002                1
         1          2 Producer                19         96          0           0          0          0 P000                1

So, there is on DFO  tree, three TQ(table queue), and P000,P001,P002 not only acted as Consumer, but also Producer. The DFO tree can be visualized(the rectangle stands for table queue, and ellipse stands for servers/slaves :

image

There are quite a lot of queries that have multiple DFO trees, just a demonstration innovated from Jonathan’s blog 

select /*+ parallel(t1 4) parallel(v1 8 ) */
 t1.id
  from t1,
       (select /*+ parallel(t1 4) parallel(t2 4) */
         rownum, t1.id
          from t1, t2
         where t1.id = t2.id) v1
 where t1.id = v1.id;


Execution plan:

-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |          |   100 |   600 |     7  (15)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR                 |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)           | :TQ20002 |   100 |   600 |     7  (15)| 00:00:01 |  Q2,02 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN                    |          |   100 |   600 |     7  (15)| 00:00:01 |  Q2,02 | PCWP |            |
|   4 |     PX RECEIVE                  |          |   100 |   300 |     2   (0)| 00:00:01 |  Q2,02 | PCWP |            |
|   5 |      PX SEND HASH               | :TQ20001 |   100 |   300 |     2   (0)| 00:00:01 |  Q2,01 | P->P | HASH       |
|   6 |       PX BLOCK ITERATOR         |          |   100 |   300 |     2   (0)| 00:00:01 |  Q2,01 | PCWC |            |
|   7 |        TABLE ACCESS FULL        | T1       |   100 |   300 |     2   (0)| 00:00:01 |  Q2,01 | PCWP |            |
|   8 |     BUFFER SORT                 |          |       |       |            |          |  Q2,02 | PCWC |            |
|   9 |      PX RECEIVE                 |          |   100 |   300 |     5  (20)| 00:00:01 |  Q2,02 | PCWP |            |
|  10 |       PX SEND HASH              | :TQ20000 |   100 |   300 |     5  (20)| 00:00:01 |        | S->P | HASH       |
|  11 |        VIEW                     |          |   100 |   300 |     5  (20)| 00:00:01 |        |      |            |
|  12 |         COUNT                   |          |       |       |            |          |        |      |            |
|  13 |          PX COORDINATOR         |          |       |       |            |          |        |      |            |
|  14 |           PX SEND QC (RANDOM)   | :TQ10002 |   100 |   600 |     5  (20)| 00:00:01 |  Q1,02 | P->S | QC (RAND)  |
|* 15 |            HASH JOIN BUFFERED   |          |   100 |   600 |     5  (20)| 00:00:01 |  Q1,02 | PCWP |            |
|  16 |             PX RECEIVE          |          |   100 |   300 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
|  17 |              PX SEND HASH       | :TQ10000 |   100 |   300 |     2   (0)| 00:00:01 |  Q1,00 | P->P | HASH       |
|  18 |               PX BLOCK ITERATOR |          |   100 |   300 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|  19 |                TABLE ACCESS FULL| T1       |   100 |   300 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
|  20 |             PX RECEIVE          |          |   100 |   300 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
|  21 |              PX SEND HASH       | :TQ10001 |   100 |   300 |     2   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |
|  22 |               PX BLOCK ITERATOR |          |   100 |   300 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
|  23 |                TABLE ACCESS FULL| T2       |   100 |   300 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
-------------------------------------------------------------------------------------------------------------------------

Information from v$pq_tqstat;

hlr@ORCL> select * from v$pq_tqstat  order by dfo_number , tq_id , server_type;

DFO_NUMBER      TQ_ID SERVER_TYPE       NUM_ROWS      BYTES  OPEN_TIME AVG_LATENCY      WAITS   TIMEOUTS PROCESS      INSTANCE
---------- ---------- --------------- ---------- ---------- ---------- ----------- ---------- ---------- ---------- ----------
         1          0 Consumer                27        128          0           0         14          8 P003                1
         1          0 Consumer                19         96          0           0         12          6 P000                1
         1          0 Consumer                26        124          0           0         12          6 P001                1
         1          0 Consumer                28        132          0           0         14          8 P002                1
         1          1 Consumer                27        188          0           0         13          7 P003                1
         1          1 Consumer                26        184          0           0         14          9 P001                1
         1          1 Consumer                28        192          0           0         11          6 P002                1
         1          1 Consumer                19        156          0           0         14          9 P000                1
         1          1 Producer                 0         80          0           0          0          0 P006                1
         1          1 Producer               100        480          0           0          1          0 P004                1
         1          1 Producer                 0         80          0           0          0          0 P005                1
         1          1 Producer                 0         80          0           0          0          0 P007                1
         1          2 Producer                26        124          0           0          0          0 P001                1
         1          2 Producer                19         96          0           0          0          0 P000                1
         1          2 Producer                28        132          0           0          0          0 P002                1
         1          2 Producer                27        128          0           0          0          0 P003                1
         2          0 Consumer                26        184          0           0         14          7 P009                1
         2          0 Consumer                19        156          0           0         15          8 P008                1
         2          0 Consumer                28        192          0           0         13          7 P010                1
         2          0 Consumer                27        188          0           0         13          8 P011                1
         2          0 Producer               100        480          0           0          2          1 P016                1
         2          0 Producer                 0         80          0           0          0          0 P013                1
         2          0 Producer               100        480          0           0 4294967242 4294967282 QC                  1
         2          0 Producer                 0         80          0           0          0          0 P014                1
         2          0 Producer                 0         80          0           0          0          0 P012                1
         2          1 Consumer                19        156          0           0         14          8 P008                1
         2          1 Consumer                27        188          0           0         14          8 P011                1
         2          1 Consumer                28        192          0           0         16          7 P010                1
         2          1 Consumer                26        184          0           0         13          7 P009                1
         2          1 Producer               100        480          0           0          1          0 P016                1
         2          1 Producer                 0         80          0           0          0          0 P014                1
         2          1 Producer                 0         80          0           0          0          0 P012                1
         2          1 Producer                 0         80          0           0          0          0 P013                1
         2          2 Consumer               100        480          0           0          2          1 QC                  1
         2          2 Consumer               100        480          0           0          4          2 QC                  1
         2          2 Producer                28        132          0           0          0          0 P010                1
         2          2 Producer                27        128          0           0          0          0 P011                1
         2          2 Producer                19         96          0           0          0          0 P008                1
         2          2 Producer                26        124          0           0          0          0 P009                1

SO, there are two DFO trees. Also, the DFO trees can be visualized:

image

Questions is: there are two QC in TQ(2,2), which have different waits and timeouts in v$pq_tqstat. And the TQ(1,0) have no producers in the v$pq_tqstat, I just add it for completion.

Monitor parallel execution

After the parallel execution, this is the best chance to query the execution information.
For Example, to analyze the execution of following parallel SQL statement.

select /*+ ordered use_hash(p c) parallel(p 4) parallel(c 4) pq_distribute(c hash, hash)*/
 c.unit_price
  from products p, costs c
 where c.prod_id = p.prod_id;

After execution,

hlr@ORCL> select * from v$pq_sesstat;

STATISTIC                      LAST_QUERY SESSION_TOTAL
------------------------------ ---------- -------------
Queries Parallelized                    1            13
DML Parallelized                        0             0
DDL Parallelized                        0             0
DFO Trees                               1            13
Server Threads                          6             0
Allocation Height                       3             0
Allocation Width                        1             0
Local Msgs Sent                       362        303740
Distr Msgs Sent                         0             0
Local Msgs Recv'd                     368        303782
Distr Msgs Recv'd                       0             0

11 rows selected.

hlr@ORCL> select  DFO_NUMBER, TQ_ID, SERVER_TYPE,  NUM_ROWS ,BYTES,process from v$pq_tqstat order by dfo_number , tq_id , server_type;

DFO_NUMBER      TQ_ID SERVER_TYPE       NUM_ROWS      BYTES PROCESS
---------- ---------- --------------- ---------- ---------- --------
         1          0 Consumer             17151     100454 P001
         1          0 Consumer             17242     100969 P002
         1          0 Consumer             17257     101058 P000
         1          0 Producer              1971       9955 P004
         1          0 Producer             29565     174989 P005
         1          0 Producer             20114     117537 P003
         1          1 Consumer               893       8107 P002
         1          1 Consumer              2914      26341 P001
         1          1 Consumer                 0         60 P000
         1          1 Producer               611       5494 P003
         1          1 Producer              2593      23493 P005
         1          1 Producer               603       5521 P004
         1          2 Consumer              3807      19040 QC
         1          2 Producer              2914      14545 P001
         1          2 Producer               893       4475 P002
         1          2 Producer                 0         20 P000

16 rows selected.

hlr@ORCL>

Obviously, from the v$pq_tqstat, the DOP is downgrade to 3, and have two slave sets.  From the v$tq_sesstat, we can see that what’s the process. How these processes cooperated together to generated the result. In this sample, P003, P004,P005 generate the data and feed to P000,P001,P002, totally twice. Then P000,P001,P002 feed the data to QC, the query coordinator. Also, we can find that P000 at the first time received 17257 rows, but at the second time it received 0 rows, and lastly, it product 0 rows to QC. Why?

Let’s look at the execution plan for further investigation.


hlr@ORCL> explain plan for select /*+ ordered use_hash(p c) parallel(p 4) parallel(c 4) pq_distribute(c hash, hash)*/ c.unit_price from products p, costs c where c.prod_id = p.prod_id;

Explained.

hlr@ORCL> @utlxplp

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1177066807

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |          |  3867 |   147K|    13   (8)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR         |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)   | :TQ10002 |  3867 |   147K|    13   (8)| 00:00:01 |  Q1,02 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN BUFFERED   |          |  3867 |   147K|    13   (8)| 00:00:01 |  Q1,02 | PCWP |            |
|   4 |     PX RECEIVE          |          | 53332 |   677K|     7   (0)| 00:00:01 |  Q1,02 | PCWP |            |
|   5 |      PX SEND HASH       | :TQ10000 | 53332 |   677K|     7   (0)| 00:00:01 |  Q1,00 | P->P | HASH       |
|   6 |       PX BLOCK ITERATOR |          | 53332 |   677K|     7   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   7 |        TABLE ACCESS FULL| PRODUCTS | 53332 |   677K|     7   (0)| 00:00:01 |  Q1,00 | PCWP |            |
|   8 |     PX RECEIVE          |          |  3867 |    98K|     5   (0)| 00:00:01 |  Q1,02 | PCWP |            |
|   9 |      PX SEND HASH       | :TQ10001 |  3867 |    98K|     5   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |
|  10 |       PX BLOCK ITERATOR |          |  3867 |    98K|     5   (0)| 00:00:01 |  Q1,01 | PCWC |            |
|  11 |        TABLE ACCESS FULL| COSTS    |  3867 |    98K|     5   (0)| 00:00:01 |  Q1,01 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("C"."PROD_ID"="P"."PROD_ID")

Note
-----
   - dynamic sampling used for this statement

27 rows selected.

hlr@ORCL>

This is a hash-hash parallel distribute, using hash joining. firstly, Slave set(Q1,00) scan products table and send the results to slave set(Q1,02), and slave set(Q1,01) scan the costs table and send results to slave set(Q1,02), which slave in slave set(Q1,02) to send to is dependent on the hash value of join key. as the table costs only have two distinct values for prod_id, so the rows in costs only have two target slave to send to, resulting one slave of the slave set (Q1,02) receive 0 rows. After the slaves in (Q1,02) received  rows from the other two slave sets, they hash join the rows and send the result to QC, obviously, one slave will have no rows to process.

This is why 0 rows in the above output.

Also, you can enable the trace for parallel execution, through this way:

alter session set events '10132 trace name context forever';

As a summary, we can monitor the parallel executions through v$ views, execution plan and trace event.

Parallel Query Distribution Combinations and Hints

The PQ_DISTRIBUTE hint instructs the optimizer how to distribute rows of joined tables among producer and consumer query servers. Such distribution can improve the performance of parallel join operations.

 image

tablespec is the name or alias of a table to be used as the inner table of a join.
outer_distribution is the distribution for the outer table.
inner_distribution is the distribution for the inner table.
The values of the distributions are HASH, BROADCAST, PARTITION, and NONE. Only six combinations table distributions are valid, as described in the table below:

Distribution Description
HASH, HASH

The rows of each table are mapped to consumer query servers, using a hash function on the join keys. When mapping is complete, each query server performs the join between a pair of resulting partitions. This distribution is recommended when the tables are comparable in size and the join operation is implemented by hash-join or sort merge join.

BROADCAST, NONE

All rows of the outer table are broadcast to each query server. The inner table rows are randomly partitioned. This distribution is recommended when the outer table is very small compared with the inner table. As a general rule, use this distribution when the inner table size multiplied by the number of query servers is greater than the outer table size.

NONE, BROADCAST

All rows of the inner table are broadcast to each consumer query server. The outer table rows are randomly partitioned. This distribution is recommended when the inner table is very small compared with the outer table. As a general rule, use this distribution when the inner table size multiplied by the number of query servers is less than the outer table size.

PARTITION, NONE

The rows of the outer table are mapped using the partitioning of the inner table. The inner table must be partitioned on the join keys. This distribution is recommended when the number of partitions of the outer table is equal to or nearly equal to a multiple of the number of query servers; for example, 14 partitions and 15 query servers.
Note: The optimizer ignores this hint if the inner table is not partitioned or not equijoined on the partitioning key.

NONE, PARTITION

The rows of the inner table are mapped using the partitioning of the outer table. The outer table must be partitioned on the join keys. This distribution is recommended when the number of partitions of the outer table is equal to or nearly equal to a multiple of the number of query servers; for example, 14 partitions and 15 query servers.
Note: The optimizer ignores this hint if the outer table is not partitioned or not equijoined on the partitioning key.

NONE, NONE

Each query server performs the join operation between a pair of matching partitions, one from each table. Both tables must be equipartitioned on the join keys.

For example, given two tables r and s that are joined using a hash join, the following query contains a hint to use hash distribution:

SELECT /*+ORDERED PQ_DISTRIBUTE(s HASH, HASH) USE_HASH (s)*/ column_list
FROM r,s
WHERE r.c=s.c;


To broadcast the outer table r, the query is:

SELECT /*+ORDERED PQ_DISTRIBUTE(s BROADCAST, NONE) USE_HASH (s) */ column_list
FROM r,s
WHERE r.c=s.c;

This is just reference from Oracle 10g online document.

My examples to demonstrate these concepts

system@ORCL> create table products as select rownum prod_id from all_objects;

Table created.

system@ORCL> create table costs as select mod(rownum,2)+1 prod_id, rownum unit_price from all_tables;

Table created.

system@ORCL> set autot trace expl;
system@ORCL> select /*+ ordered use_hash(p c) parallel(p 4) parallel(c 4) pq_distribute(c hash, hash)*/ c.unit_price from products p, costs c where c.prod_id = p.prod_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 1177066807

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |          |  1790 | 69810 |     9  (12)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR         |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)   | :TQ10002 |  1790 | 69810 |     9  (12)| 00:00:01 |  Q1,02 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN BUFFERED   |          |  1790 | 69810 |     9  (12)| 00:00:01 |  Q1,02 | PCWP |            |
|   4 |     PX RECEIVE          |          | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,02 | PCWP |            |
|   5 |      PX SEND HASH       | :TQ10000 | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,00 | P->P | HASH       |
|   6 |       PX BLOCK ITERATOR |          | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,00 | PCWC |            |
|   7 |        TABLE ACCESS FULL| PRODUCTS | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,00 | PCWP |            |
|   8 |     PX RECEIVE          |          |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
|   9 |      PX SEND HASH       | :TQ10001 |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |
|  10 |       PX BLOCK ITERATOR |          |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
|  11 |        TABLE ACCESS FULL| COSTS    |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("C"."PROD_ID"="P"."PROD_ID")

Note
-----
   - dynamic sampling used for this statement

system@ORCL> select /*+ ordered use_hash(p c) parallel(p 4) parallel(c 4) pq_distribute(c broadcast, none)*/ c.unit_price from products p, costs c where c.prod_id = p.prod_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 1844745828

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |          |  1790 | 69810 |     9  (12)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR         |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)   | :TQ10001 |  1790 | 69810 |     9  (12)| 00:00:01 |  Q1,01 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN            |          |  1790 | 69810 |     9  (12)| 00:00:01 |  Q1,01 | PCWP |            |
|   4 |     PX RECEIVE          |          | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,01 | PCWP |            |
|   5 |      PX SEND BROADCAST  | :TQ10000 | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,00 | P->P | BROADCAST  |
|   6 |       PX BLOCK ITERATOR |          | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,00 | PCWC |            |
|   7 |        TABLE ACCESS FULL| PRODUCTS | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,00 | PCWP |            |
|   8 |     PX BLOCK ITERATOR   |          |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
|   9 |      TABLE ACCESS FULL  | COSTS    |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("C"."PROD_ID"="P"."PROD_ID")

Note
-----
   - dynamic sampling used for this statement

system@ORCL> select /*+ ordered use_hash(p c) parallel(p 4) parallel(c 4) pq_distribute(c none broadcast)*/ c.unit_price from products p, costs c where c.prod_id = p.prod_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 2231521328

------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |          |  1790 | 69810 |     9  (12)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR          |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)    | :TQ10001 |  1790 | 69810 |     9  (12)| 00:00:01 |  Q1,01 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN             |          |  1790 | 69810 |     9  (12)| 00:00:01 |  Q1,01 | PCWP |            |
|   4 |     PX BLOCK ITERATOR    |          | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,01 | PCWC |            |
|   5 |      TABLE ACCESS FULL   | PRODUCTS | 51613 |   655K|     7  (15)| 00:00:01 |  Q1,01 | PCWP |            |
|   6 |     BUFFER SORT          |          |       |       |            |          |  Q1,01 | PCWC |            |
|   7 |      PX RECEIVE          |          |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
|   8 |       PX SEND BROADCAST  | :TQ10000 |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,00 | P->P | BROADCAST  |
|   9 |        PX BLOCK ITERATOR |          |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|  10 |         TABLE ACCESS FULL| COSTS    |  1790 | 46540 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("C"."PROD_ID"="P"."PROD_ID")

Note
-----
   - dynamic sampling used for this statement

Parallel Partitioning Execution Plan

Two execution plans.

Disable optimizer_dynamic_sampling firstly.

alter session set optimizer_dynamic_sampling = 0;

Then, create two simple tables;

CREATE TABLE t1 ( c1 NUMBER, c2 NUMBER );
CREATE TABLE t2 ( c1 NUMBER, c2 NUMBER );
hr@ORCL>  SELECT /*+ parallel(t1,2) */ t1.c2,t2.c2 FROM t1,t2 WHERE t1.c1 = t2.c1;

Execution Plan
----------------------------------------------------------
Plan hash value: 869483324

------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |          |    82 |  4264 |     5  (20)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR          |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)    | :TQ10001 |    82 |  4264 |     5  (20)| 00:00:01 |  Q1,01 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN             |          |    82 |  4264 |     5  (20)| 00:00:01 |  Q1,01 | PCWP |            |
|   4 |     PX BLOCK ITERATOR    |          |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
|   5 |      TABLE ACCESS FULL   | T1       |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
|   6 |     BUFFER SORT          |          |       |       |            |          |  Q1,01 | PCWC |            |
|   7 |      PX RECEIVE          |          |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
|   8 |       PX SEND BROADCAST  | :TQ10000 |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,00 | P->P | BROADCAST  |
|   9 |        PX BLOCK ITERATOR |          |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|  10 |         TABLE ACCESS FULL| T2       |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("T1"."C1"="T2"."C1")

hr@ORCL>  SELECT /*+ parallel(t1,3) */ t1.c2,t2.c2 FROM t1,t2 WHERE t1.c1 = t2.c1;

Execution Plan
----------------------------------------------------------
Plan hash value: 3683239666

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |          |    82 |  4264 |     5  (20)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR         |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)   | :TQ10002 |    82 |  4264 |     5  (20)| 00:00:01 |  Q1,02 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN BUFFERED   |          |    82 |  4264 |     5  (20)| 00:00:01 |  Q1,02 | PCWP |            |
|   4 |     PX RECEIVE          |          |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
|   5 |      PX SEND HASH       | :TQ10000 |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,00 | P->P | HASH       |
|   6 |       PX BLOCK ITERATOR |          |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   7 |        TABLE ACCESS FULL| T1       |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
|   8 |     PX RECEIVE          |          |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
|   9 |      PX SEND HASH       | :TQ10001 |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |
|  10 |       PX BLOCK ITERATOR |          |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
|  11 |        TABLE ACCESS FULL| T2       |    82 |  2132 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("T1"."C1"="T2"."C1")

Why the PQ distribution change from Broadcast to Hash when DOP(degree of parallel) changes from 2 to 3(or above)?

Note that TQ(Table Queue) also change from 2 to 3.

But let’s change to another principle questions, how many PQ distribute way exists? Can I change them by my own? Refer to my next article for answers.

Another principle question: how to monitor the parallel execution except the execution plan? how about the trace, V$ views, or other things? Refer to my next next article for answers!

So why the optimizer chose different execution plan according to different DOP? Simple to say, this is based on the statistics on the tables. And here, remember, the statistics for these tables here are all "default" statistics, which is not suitable for parallel execution actually. Where to use a specific PQ distribute method could be another deep topic.

Create two partitioned tables:

CREATE TABLE t1(c1 NUMBER, c2 NUMBER)
PARTITION BY RANGE (c1)
  (
   PARTITION p1 VALUES LESS THAN (10),
   PARTITION p2 VALUES LESS THAN (20),
   PARTITION p3 VALUES LESS THAN (30),
   PARTITION p4 VALUES LESS THAN (40)
  );

CREATE TABLE t2(c1 NUMBER, c2 NUMBER)
PARTITION BY RANGE (c1)
(
   PARTITION p1 VALUES LESS THAN (10),
   PARTITION p2 VALUES LESS THAN (20),
   PARTITION p3 VALUES LESS THAN (30),
   PARTITION p4 VALUES LESS THAN (40)
);

 

hr@ORCL>  SELECT /*+ PARALLEL (t1,1) */ t1.c2 FROM t1,t2 WHERE t1.c1 = t2.c1;

Execution Plan
----------------------------------------------------------
Plan hash value: 1604022418

--------------------------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |   328 | 12792 |     8  (25)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE ALL|      |   328 | 12792 |     8  (25)| 00:00:01 |     1 |     4 |
|*  2 |   HASH JOIN         |      |   328 | 12792 |     8  (25)| 00:00:01 |       |       |
|   3 |    TABLE ACCESS FULL| T1   |   328 |  8528 |     3   (0)| 00:00:01 |     1 |     4 |
|   4 |    TABLE ACCESS FULL| T2   |   328 |  4264 |     3   (0)| 00:00:01 |     1 |     4 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("T1"."C1"="T2"."C1")

hr@ORCL>  SELECT /*+ PARALLEL (t1,2) */ t1.c2 FROM t1,t2 WHERE t1.c1 = t2.c1;

Execution Plan
----------------------------------------------------------
Plan hash value: 2042620038

--------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |          |   328 | 12792 |     6  (17)| 00:00:01 |       |       |        |      |            |
|   1 |  PX COORDINATOR              |          |       |       |            |          |       |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)        | :TQ10001 |   328 | 12792 |     6  (17)| 00:00:01 |       |       |  Q1,01 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN                 |          |   328 | 12792 |     6  (17)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   4 |     PX BLOCK ITERATOR        |          |   328 |  8528 |     2   (0)| 00:00:01 |     1 |     4 |  Q1,01 | PCWC |            |
|   5 |      TABLE ACCESS FULL       | T1       |   328 |  8528 |     2   (0)| 00:00:01 |     1 |     4 |  Q1,01 | PCWP |            |
|   6 |     BUFFER SORT              |          |       |       |            |          |       |       |  Q1,01 | PCWC |            |
|   7 |      PX RECEIVE              |          |   328 |  4264 |     3   (0)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   8 |       PX SEND BROADCAST LOCAL| :TQ10000 |   328 |  4264 |     3   (0)| 00:00:01 |       |       |        | S->P | BCST LOCAL |
|   9 |        PARTITION RANGE ALL   |          |   328 |  4264 |     3   (0)| 00:00:01 |     1 |     4 |        |      |            |
|  10 |         TABLE ACCESS FULL    | T2       |   328 |  4264 |     3   (0)| 00:00:01 |     1 |     4 |        |      |            |
--------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("T1"."C1"="T2"."C1")

hr@ORCL>  SELECT /*+ PARALLEL (t1,4) */ t1.c2 FROM t1,t2 WHERE t1.c1 = t2.c1;

Execution Plan
----------------------------------------------------------
Plan hash value: 2117927142

-----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |          |   328 | 12792 |     6  (17)| 00:00:01 |       |       |        |      |            |
|   1 |  PX COORDINATOR           |          |       |       |            |          |       |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)     | :TQ10001 |   328 | 12792 |     6  (17)| 00:00:01 |       |       |  Q1,01 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN              |          |   328 | 12792 |     6  (17)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   4 |     PX BLOCK ITERATOR     |          |   328 |  8528 |     2   (0)| 00:00:01 |     1 |     4 |  Q1,01 | PCWC |            |
|   5 |      TABLE ACCESS FULL    | T1       |   328 |  8528 |     2   (0)| 00:00:01 |     1 |     4 |  Q1,01 | PCWP |            |
|   6 |     BUFFER SORT           |          |       |       |            |          |       |       |  Q1,01 | PCWC |            |
|   7 |      PX RECEIVE           |          |   328 |  4264 |     3   (0)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   8 |       PX SEND BROADCAST   | :TQ10000 |   328 |  4264 |     3   (0)| 00:00:01 |       |       |        | S->P | BROADCAST  |
|   9 |        PARTITION RANGE ALL|          |   328 |  4264 |     3   (0)| 00:00:01 |     1 |     4 |        |      |            |
|  10 |         TABLE ACCESS FULL | T2       |   328 |  4264 |     3   (0)| 00:00:01 |     1 |     4 |        |      |            |
-----------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("T1"."C1"="T2"."C1")

hr@ORCL>  SELECT /*+ PARALLEL (t1,5) */ t1.c2 FROM t1,t2 WHERE t1.c1 = t2.c1;

Execution Plan
----------------------------------------------------------
Plan hash value: 2042834191

--------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |          |   328 | 12792 |     6  (17)| 00:00:01 |       |       |        |      |            |
|   1 |  PX COORDINATOR              |          |       |       |            |          |       |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)        | :TQ10001 |   328 | 12792 |     6  (17)| 00:00:01 |       |       |  Q1,01 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN                 |          |   328 | 12792 |     6  (17)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   4 |     PX PARTITION RANGE ALL   |          |   328 |  8528 |     2   (0)| 00:00:01 |     1 |     4 |  Q1,01 | PCWC |            |
|   5 |      TABLE ACCESS FULL       | T1       |   328 |  8528 |     2   (0)| 00:00:01 |     1 |     4 |  Q1,01 | PCWP |            |
|   6 |     BUFFER SORT              |          |       |       |            |          |       |       |  Q1,01 | PCWC |            |
|   7 |      PX RECEIVE              |          |   328 |  4264 |     3   (0)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   8 |       PX SEND PARTITION (KEY)| :TQ10000 |   328 |  4264 |     3   (0)| 00:00:01 |       |       |        | S->P | PART (KEY) |
|   9 |        PARTITION RANGE ALL   |          |   328 |  4264 |     3   (0)| 00:00:01 |     1 |     4 |        |      |            |
|  10 |         TABLE ACCESS FULL    | T2       |   328 |  4264 |     3   (0)| 00:00:01 |     1 |     4 |        |      |            |
--------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("T1"."C1"="T2"."C1")

hr@ORCL>

Also the PQ distribution change from "Broadcast Local" to "Broadcast" to "Part(Key)" when DOP(degree of parallel) changes from 2 to 4 to 5(or above).

Why?  Maybe, in the further, I will use an more realistic case to study and investigate why.

Installation Apache + PHP + OCI + Mysql + PHPMyAdmin in 5 Minutes

Compiling from source is not an productive way to install software, the binary distribution will cease a lot of trouble when installing. It will be perfect will one distribution vendor bundle all of the necessary development software together and make the common configuration and optimization, and make the management easy to combine some management tools.

Zend Core for Oracle come out! "Zend Core is a Certified PHP distribution that includes a stable and reliable environment for managing PHP. This environment improves PHP development by removing the current hardship in manually building and setting up an entire PHP environment. Zend Core also acts as an "efficiency facilitator" to improve the PHP implementation and management process for managing PHP development and production environments.
Zend Core does not require any complicated configurations or settings in order to run. After installation, Zend Core is ready to run. The only thing left to do is to login to the application with the password that was created in the installation process."

The URL to download the latest version: http://www.oracle.com/technology/tech/php/zendcore/index.html

Just download it and execute the install scripts, remember to install the additional components, including Zend Framework, Mysql, PHPMyAdmin.

After installing, the directory layout(in /usr/local/Zend) is like:

|– Core
|   |– GUI
|   |– bin
|   |– cgi-bin
|   |– etc
|   |– include
|   |– lib
|   |– logs
|   |– modules
|   |– mysql
|   |– sbin
|   |– setup
|   `– share
|– ZendFramework
|   |– INSTALL.txt
|   |– LICENSE.txt
|   |– NEWS.txt
|   |– README.txt
|   |– VERSION.txt
|   |– demos
|   |– library
|   `– tests
`– apache2
    |– LICENSE
    |– bin
    |– build
    |– cgi-bin
    |– conf
    |– error
    |– htdocs
    |– icons
    |– include
    |– lib
    |– logs
    |– man
    |– manual
    `– modules

And the Web page is like this:

image

The Mysql link to PHPMyAdmin:

image

All is ready for you to explore!

For example, let’s test the OCI functionalities:

create the file conn.php as last article, and output is like this:

 image

Traditional Way for Installing PHP(OCI enabled) + Apache on Linux

Actually, the traditional way is compiling source from scratch. Below is information from OTN:
Installing Apache, PHP, JDeveloper, and the PHP Extension on Linux

Apache 1.3

  1. Login as Oracle user.
  2. Copy/download apache_1.3.31.tar.gz
  3. tar -zxf apache_1.3.31.tar.gz
  4. cd apache_1.3.31
  5. Configure:
    ./configure --enable-module=so --prefix=$HOME/apache --with-port=8888
  6. Build: make
  7. Install: make install
  8. Start Apache: $HOME/apache/bin/apachectl start
  9. Go to a browser and check that http://localhost:8888/ returns the default "Powered by Apache" page.
  10. Stop Apache: $HOME/apache/bin/apachectl stop

PHP 4.3

Before you proceed, make sure that the packages "bison" and "flex" are installed, because PHP needs them.

  1. Copy/download php-4.3.9.tar.gz
  2. tar -zxf php-4.3.9.tar.gz
  3. Set environment variable ORACLE_SID
  4. Set environment variable ORACLE_HOME
  5. Set environment variable LD_LIBRARY_PATH to $ORACLE_HOME/lib:${LD_LIBRARY_PATH}
  6. Configure (make sure to enter this as one long line):
    ./configure --prefix=$HOME/php --with-apxs=$HOME/apache/bin/apxs
     --with-config-file-path=$HOME/apache/conf
     --with-oci8=$ORACLE_HOME --enable-sigchild
  7. Build: make
  8. Install: Make install
  9. cp php.ini-recommended $HOME/apache/conf/php.ini
  10. Edit $HOME/apache/conf/httpd.conf and add:
    AddType application/x-httpd-php        .php
    AddType application/x-httpd-php-source .phps

  11. Restart Apache
  12. create $HOME/apache/htdocs/phpinfo.php as:
       1: <?php
       2:   phpinfo();
       3: ?>

  13. In a browser load http://localhost:8888/phpinfo.php. Check that the OCI module is listed.

Following exactly the steps above, you will get PHP + Apache running on Linux.

NOTES:–with-apxs in step 6 when installing PHP is important, this let the installation process to compile the OCI library for the apache and make it available to Apache.

For testing the OCI support in PHP, create $HOME/apache/htdocs/connect.php as:

   1: <?php 
   2:  
   3: define('ORA_CON_UN', 'scott');
   4: define('ORA_CON_PW', 'tiger');
   5: define('ORA_CON_DB', 'MYSID');
   6:  
   7: $conn = OCILogon(ORA_CON_UN, ORA_CON_PW , ORA_CON_DB );
   8:  
   9: if (!$conn) {
  10: exit;
  11:   }
  12:  
  13: echo OCIServerVersion($conn) ."<br>\n";
  14: echo "Connected as ".ORA_CON_UN."</br>\n";
  15: echo date('Y-m-d H:i:s')."<br><br>\n";
  16:  
  17: $query = 'select * from emp';
  18:  
  19: $stid = OCIParse($conn, $query);
  20: OCIExecute($stid, OCI_DEFAULT);
  21: print "<table border='1'>\n";
  22: while ($succ = OCIFetchInto($stid, $row, OCI_RETURN_NULLS)) {
  23: print "<tr>\n";
  24: foreach ($row as $item) {
  25: print '<td>';
  26: print isset($item)?htmlentities($item):'?';
  27: print "</td>\n";
  28:     }
  29: print "</tr>\n";
  30:   }
  31: print "</table>\n";
  32:  
  33: OCILogoff($conn);
  34: ?>

In a browser load http://localhost:8888/connect.php. Check that the OCI driver works.