NO_PARALLEL Hint als Beispiel


Dieses Beispiel soll den Einsatz den NO_PARALLEL Hints zeigen.

SQL> r
  1  select owner,table_name, degree
  2        from dba_tables
  3*       where table_name in ('EMPLOYEES','DEPARTMENTS')

OWNER                          TABLE_NAME                     DEGREE
------------------------------ ------------------------------ ----------------------------------------
HR                             EMPLOYEES                      1
HR                             DEPARTMENTS                    1

Wie wir sehen können ist der „Degree“ auf Tabellen Ebene 1, was bedeutet das wir diesen erst für unser Beispiel ändern müssen.

SQL> alter table hr.employees parallel (degree 4);

Table altered.

SQL> alter table hr.departments parallel (degree 4);

Table altered.

Führen wir jetzt unser SQL Statement aus sehen wir die Parallele Ausführung.

select e.LAST_NAME , d.DEPARTMENT_NAME
from EMPLOYEES e , DEPARTMENTS d
where  e.DEPARTMENT_ID = d.DEPARTMENT_ID;
--------------------------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name          | Rows  | Bytes | Cost (%CPU) | Time     |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |               |   106 |  2862 |     5  (20) | 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR                 |               |       |       |             |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)           | :TQ10002      |   106 |  2862 |     5  (20) | 00:00:01 |  Q1,02 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN BUFFERED           |               |   106 |  2862 |     5  (20) | 00:00:01 |  Q1,02 | PCWP |            |
|   4 |     PX RECEIVE                  |               |    27 |   432 |     2    (0)| 00:00:01 |  Q1,02 | PCWP |            |
|   5 |      PX SEND HASH               | :TQ10000      |    27 |   432 |     2    (0)| 00:00:01 |  Q1,00 | P->P | HASH       |
|   6 |       PX BLOCK ITERATOR         |               |    27 |   432 |     2    (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   7 |        TABLE ACCESS FULL        | DEPARTMENTS   |    27 |   432 |     2    (0)| 00:00:01 |  Q1,00 | PCWP |            |
|   8 |     PX RECEIVE                  |               |   107 |  1177 |     2    (0)| 00:00:01 |  Q1,02 | PCWP |            |
|   9 |      PX SEND HASH               | :TQ10001      |   107 |  1177 |     2    (0)| 00:00:01 |  Q1,01 | P->P | HASH       |
|  10 |       PX BLOCK ITERATOR         |               |   107 |  1177 |     2    (0)| 00:00:01 |  Q1,01 | PCWC |            |
|  11 |        TABLE ACCESS FULL        | EMPLOYEES     |   107 |  1177 |     2    (0)| 00:00:01 |  Q1,01 | PCWP |            |
--------------------------------------------------------------------------------------------------------------------

Wir können im Execution Plan gut erkennen das wir dieses SQL Statement Parallel ausgeführt haben.

Testen wir nun unseren Parallel HINT.

select /*+ no_parallel(d) */ e.LAST_NAME , d.DEPARTMENT_NAME
from EMPLOYEES e , DEPARTMENTS d
where  e.DEPARTMENT_ID = d.DEPARTMENT_ID;
-------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name         | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |              |   106 |  2862 |     5  (20)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR                |              |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)          | :TQ10001     |   106 |  2862 |     5  (20)| 00:00:01 |  Q1,01 | P->S | QC (RAND)  |
|   3 |    MERGE JOIN                  |              |   106 |  2862 |     5  (20)| 00:00:01 |  Q1,01 | PCWP |            |
|   4 |     SORT JOIN                  |              |    27 |   432 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
|   5 |      BUFFER SORT               |              |       |       |            |          |  Q1,01 | PCWC |            |
|   6 |       PX RECEIVE               |              |    27 |   432 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
|   7 |        PX SEND BROADCAST       | :TQ10000     |    27 |   432 |     2   (0)| 00:00:01 |        | S->P | BROADCAST  |
|   8 |     TABLE ACCESS BY INDEX ROWID| DEPARTMENTS  |    27 |   432 |     2   (0)| 00:00:01 |        |      |            |
|   9 |      INDEX FULL SCAN           | DEPT_ID_PK   |    27 |       |     1   (0)| 00:00:01 |        |      |            |
|* 10 |     SORT JOIN                  |              |   107 |  1177 |     3  (34)| 00:00:01 |  Q1,01 | PCWP |            |
|  11 |      PX BLOCK ITERATOR         |              |   107 |  1177 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
|  12 |       TABLE ACCESS FULL        | EMPLOYEES    |   107 |  1177 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
-------------------------------------------------------------------------------------------------------------------------------

Am nächsten Execution Plan können wir erkennen das der NO_PARALLEL HINT nicht dazu geführt hat, das wir das Statement Seriell ausführen sondern der HINT nur für die Tabelle DEPARTMENTS eine Änderung herbei geführt hat.

select /*+ no_parallel(e) no_parallel(d) */
    e.LAST_NAME , d.DEPARTMENT_NAME
from EMPLOYEES e , DEPARTMENTS d
where  e.DEPARTMENT_ID = d.DEPARTMENT_ID;
--------------------------------------------------------------------------------------------------
| Id  | Operation                         | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                  |                   |   106 |  2862 |     6  (34)| 00:00:01 |
|   1 |  MERGE JOIN                       |                   |   106 |  2862 |     6  (34)| 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID     | DEPARTMENTS       |    27 |   432 |     2   (0)| 00:00:01 |
|   3 |    INDEX FULL SCAN                | DEPT_ID_PK        |    27 |       |     1   (0)| 00:00:01 |
|*  4 |   SORT JOIN                       |                   |   107 |  1177 |     4  (50)| 00:00:01 |
|   5 |    VIEW                           | index$_join$_001  |   107 |  1177 |     3  (34)| 00:00:01 |
|*  6 |     HASH JOIN                     |                   |       |       |            |          |
|   7 |      INDEX FAST FULL SCAN         | EMP_DEPARTMENT_IX |   107 |  1177 |     1   (0)| 00:00:01 |
|   8 |      INDEX FAST FULL SCAN         | EMP_NAME_IX       |   107 |  1177 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

Erst in diesem Beispiel, wo wir für alle Tabellen einen NO_HINT angegeben haben, können wir erkennen das das komplette Statement Seriel ausgeführt wird.

Es gibt leider derzeit (zumindest mir) keine Möglichkeit auf SQL Ebene die Parallel Funktion abzuschalten. Weiters darf man nicht vergessen das man innerhalb eines Statements für jede „Base Table“ der NO_PARALLEL HINT benutzt werden muss. Das ein Optimizer Hint zwischen /*+ <HINT> */ zu finden ist, muss ich hoffentlich an dieser Stelle nicht mehr erwähnen.

Parallel Statements auf Session Ebene zu kontrollieren kann wie folgt aussehen:

  • ALTER SESSION DISABLE PARALLEL DML;
  • ALTER SESSION DISABLE PARALLEL DDL;
  • ALTER SESSION DISABLE PARALLEL QUERY;

Alternativ gibt es auch noch die Möglichkeit teilweise einfluss zu nehmen.

Parallel Execution auf die lokale Instance limitieren:

System:
 alter system set "parallel_force_local" = true;
Session:
 alter session set "parallel_force_local" = true;

Wie immer Freue ich mich über Kommentare.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s