Comment vérifier et activer Parallel DML (nouveauté 11.2.0.4 et 12c)

Vous utilisez Parallel Query pour manipuler des gros volumes de données, lors d’un ETL par exemple. Mais êtes vous sûrs que les inserts /*+ append */ aussi se font en parallèle ?

Voici un plan d’exécution où la partie select est en parallel mais un seul process fait l’insert:

--------------------------------------------------------------------------------------------------------------------
| Id  | Operation                          | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                   |          |     1 |     2   (0)| 00:00:01 |        |      |            |
|   1 |  LOAD AS SELECT                    | TEST     |       |            |          |        |      |            |
|   2 |   PX COORDINATOR                   |          |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM)             | :TQ10000 |     1 |     2   (0)| 00:00:01 |  Q1,00 | P->S | QC (RAND)  |
|   4 |     OPTIMIZER STATISTICS GATHERING |          |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   5 |      PX BLOCK ITERATOR             |          |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   6 |       TABLE ACCESS FULL            | TEST     |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
--------------------------------------------------------------------------------------------------------------------

Le problème ici est que le process coordinateur est le seul à faire l’insert. Il devient donc bottleneck lorsqu’on augmente le DOP.
Ce n’est pas facile à voir. On voit ça dans le plan d’exécution parce que
LOAD AS SELECT est au dessus du PX COORDINATOR, donc exécuté par le seul process coordinateur.

Ce n’est pas parce qu’une table est en parallèle que l’insert va se faire en parallèle. Il faut explicitement activer Parallel DML dans la session.

Voici le plan de la même requête après avoir fait
ALTER SESSION ENABLE PARALLEL DML;

--------------------------------------------------------------------------------------------------------------------
| Id  | Operation                          | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                   |          |     1 |     2   (0)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR                    |          |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)              | :TQ10000 |     1 |     2   (0)| 00:00:01 |  Q1,00 | P->S | QC (RAND)  |
|   3 |    LOAD AS SELECT                  | TEST     |       |            |          |  Q1,00 | PCWP |            |
|   4 |     OPTIMIZER STATISTICS GATHERING |          |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
|   5 |      PX BLOCK ITERATOR             |          |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   6 |       TABLE ACCESS FULL            | TEST     |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
--------------------------------------------------------------------------------------------------------------------

Ce sont les process parallèles TQ10000 qui font l’insert (le LOAD AS SELECT) ici et le coordinateur n’est plus bottleneck. On devient scalable et on peut augmenter le degré de parallélisme tant qu’on a des ressources CPU et I/O.

Pourquoi doit-on explicitement activer Parallel DML alors que c’est automatique pour Parallel Query ?
C’est parce en dehors de la différence de performance, le comportement en concurrence d’accès est très différent: verrouillage exclusif de la table.
Oracle ne va pas faire ça sans demande explicite. On ne peut le faire que lorsqu’on sait qu’il n’y aura pas de DML concurrent sur la table.
Sur un CREATE TABLE AS SELECT, pas besoin puisque de toute façon personne d’autre n’utilise la table.

On ne peut pas activer Parallel DML au niveau de l’instance. C’est au niveau de la session qu’on le fait. Et si on veut que ce soit automatique sans changer le code, une solution est de mettre cet alter session dans un logon trigger pour le user en question.

Et nouveauté en 11.2.0.4 et en 12c – mais non documentée – il est possible d’activer ou désactiver Parallel DML au niveau d’une requête avec les hints ENABLE_PARALLEL_DML et DISABLE_PARALLEL_DML

Des explain plan avec les différentes combinaisons dans la demo.