Vote utilisateur: 4 / 5

Etoiles activesEtoiles activesEtoiles activesEtoiles activesEtoiles inactives
 

Sans avoir besoin d'un RAC (Real Application Cluster), d'un grid ou d'un exadata, Oracle fourni en standard un mécanisme de parallelisme très poussé.

Le parallelisme peut se retrouver dans les requêtes de selection mais également dans les chargements de masse via SQL (create as select, insert into select,...)

Commençons par étudier la partie selection et les mécanismes internes d'Oracle qui permettent d'accélérer les traitements par utilisation du parallelisme.

Une requête select utilisera le parallelisme si:

  • Un ou plusieurs objets utilisés par la requête (Table, Index, Vues matérialisée...) ont été créés (ou altérés) avec l'option PARALLEL
  • Ou si la requête elle même contient un hint +PARALLEL(table dop) ou +PARALLEL_INDEX(index dop) avec dop un entier (optionnel) représentant le degré de parallelisme souhaité.
  • Dans tous les cas, si l'optimiseur considère que l'utilisation du parallelisme est bien pertinant pour la requête.

Le CBO (Cost Based Optimizer), est bien le décideur pour savoir si le recours au parallélisme est utile ou non. En fonction des valeurs en paramètre par exemple (toujours à conditions d'avoir de bonnes statistiques). L'optimiseur peut décider que pour une valeur particulière en  prédicat il est préférable de faire un table scan et dans ce cas, si la table à l'option PARALLEL ou un hint PARALLEL, le scan se fera en parallèle, alors que pour une autre valeur du même prédicat, l'utilisation d'un index est préférable et l'optimiseur peut choisir un autre plan pour cette valeur.

L'utilisation du parallelisme réduisant la plupart (voir toujours) le cout d'un scan, pour l'optimiseur, on croit à tort, que le hint /*+PARALLEL(t)* forcera le scan de la table en parallèle. Or c'est faux, il est possible et probable que l'optimiseur bascule vers se type de plan mais il reste maitre de modifier le plan s'il considère le scan comme non optimal.

Exemple :

Utilisation du hint PARALLEL mais le CBO considère le parallélisme comme non optimal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
--Modification des objets pour être sur qu'il n'y a pas d'option de parallelisme au niveau structurel
ALTER INDEX ix1 NOPARALLEL;
ALTER TABLE F_SALES_PART NOPARALLEL;
ALTER TABLE D_PRODUCT_PART NOPARALLEL;
 
--Une requête avec un hint PARALLEL sur la table de faits mais avec des prédicats très limitant
SELECT /*+PARALLEL(s) */cod_typ_pdt, TRUNC(cod_dat,'MM'), SUM(amt_sls) amt_sls, SUM(amt_dsc) amt_dsc
FROM
F_SALES_PART s,
D_PRODUCT_PART p
WHERE 
COD_DAT BETWEEN TO_DATE('2010-05-01','YYYY-MM-DD') AND TO_DATE('2010-05-31','YYYY-MM-DD')
AND s.COD_PDT=p.COD_PDT 
AND s.COD_PDT < '0000000001050'
GROUP BY 
cod_typ_pdt,TRUNC(cod_dat,'MM')
;
 
-- Le plan généré n'utilise pas le parallelisme malgrès le hint PARALLEL : Le CBO considère qu'avec ces prédcats
-- il est préférable de passer par l'index IX1 et de ne pas utiliser de parallelisme sur la table.
 
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name              | ROWS  | Bytes | COST (%CPU)| Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |                   |     1 |    50 |    24  (34)|       |       |
|   1 |  HASH GROUP BY                        |                   |     1 |    50 |    24  (34)|       |       |
|   2 |   PARTITION HASH ALL                  |                   |     1 |    50 |    23  (31)|     1 |     5 |
|*  3 |    HASH JOIN                          |                   |     1 |    50 |    23  (31)|       |       |
|   4 |     TABLE ACCESS BY LOCAL INDEX ROWID | D_PRODUCT_PART    |     1 |    17 |     3   (0)|     1 |     5 |
|*  5 |      INDEX RANGE SCAN                 | PK_D_PRODUCT_PART |     1 |       |     2   (0)|     1 |     5 |
|   6 |     PARTITION RANGE SINGLE            |                   |   105 |  3465 |    20  (35)|     3 |     3 |
|   7 |      TABLE ACCESS BY LOCAL INDEX ROWID| F_SALES_PART      |   105 |  3465 |    20  (35)|    11 |    15 |
|*  8 |       INDEX SKIP SCAN                 | IX1               |     9 |       |    10  (70)|    11 |    15 |
---------------------------------------------------------------------------------------------------------------- 

Réduisons maintenant la séléctivité de la requête:

Modification des prédicats avec une selectivité moindre
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
-- Lorsque l'on change les prédicats en réduisant ainsi la selectivité de la requête le CBO 
-- change de plan et cette fois décider de scanner la table F_SALES_PART. Le CBO considère alors que 
-- le scan en parallèle est pertinant et prends donc le hint PARALLEL
 
SELECT /*+PARALLEL(s) */cod_typ_pdt, TRUNC(cod_dat,'MM'), SUM(amt_sls) amt_sls, SUM(amt_dsc) amt_dsc
FROM
F_SALES_PART s,
D_PRODUCT_PART p
WHERE 
COD_DAT BETWEEN TO_DATE('2010-05-01','YYYY-MM-DD') AND TO_DATE('2010-05-31','YYYY-MM-DD')
AND s.COD_PDT=p.COD_PDT 
AND s.COD_PDT < '0000000091050'
GROUP BY 
cod_typ_pdt,TRUNC(cod_dat,'MM')
 
-- Le plan utilise le parallélisme et on observe l'apparition de nouvelles colonnes dans le plan (TQ, IN-OUT et PQ Distrib)
-- TQ correspond au jeu de processus esclaves en action sur l'opération
-- IN-OUT correspond au mode d'échange entre les processus
-- PQ Distrib correspond à l'argorithme de ventilation des processus fils lors des opérations faisant intervenir un chagement
-- de mode P(Parallel) ou S(Serial)
 
---------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name           | ROWS  | Bytes |TempSpc| COST (%CPU)| Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |                |   157K|  7687K|       |  1024   (4)|       |       |        |      |            |
|   1 |  PX COORDINATOR                  |                |       |       |       |            |       |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)            | :TQ10002       |   157K|  7687K|       |  1024   (4)|       |       |  Q1,02 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY                 |                |   157K|  7687K|    19M|  1024   (4)|       |       |  Q1,02 | PCWP |            |
|   4 |     PX RECEIVE                   |                |   157K|  7687K|       |  1024   (4)|       |       |  Q1,02 | PCWP |            |
|   5 |      PX SEND HASH                | :TQ10001       |   157K|  7687K|       |  1024   (4)|       |       |  Q1,01 | P->P | HASH       |
|   6 |       HASH GROUP BY              |                |   157K|  7687K|    19M|  1024   (4)|       |       |  Q1,01 | PCWP |            |
|*  7 |        HASH JOIN                 |                |   157K|  7687K|       |  1018   (3)|       |       |  Q1,01 | PCWP |            |
|   8 |         BUFFER SORT              |                |       |       |       |            |       |       |  Q1,01 | PCWC |            |
|   9 |          PX RECEIVE              |                |  1640 | 27880 |       |     8   (0)|       |       |  Q1,01 | PCWP |            |
|  10 |           PX SEND BROADCAST LOCAL| :TQ10000       |  1640 | 27880 |       |     8   (0)|       |       |        | S->P | BCST LOCAL |
|  11 |            PARTITION HASH ALL    |                |  1640 | 27880 |       |     8   (0)|     1 |     5 |        |      |            |
|* 12 |             TABLE ACCESS FULL    | D_PRODUCT_PART |  1640 | 27880 |       |     8   (0)|     1 |     5 |        |      |            |
|  13 |         PX BLOCK ITERATOR        |                |   172K|  5564K|       |  1008   (3)|     1 |     5 |  Q1,01 | PCWC |            |
|* 14 |          TABLE ACCESS FULL       | F_SALES_PART   |   172K|  5564K|       |  1008   (3)|    11 |    15 |  Q1,01 | PCWP |            |
--------------------------------------------------------------------------------------------------------------------------------------------- 

La table F_SALES_PART est partitionnée en Range sur le COD_DAT et sous-partitionnée en hash sur le COD_PDT.
La table D_PRODUCT_PART est partitionné en hash sur le COD_PDT.
On peut légitimement se poser la question de pourquoi l'optimiseur ne réalise pas un partition wise join (cf. article sur le paritionnement).
La table D_PRODUCT_PART n'ayant pas l'option PARALLEL et la requête n'ayant pas de hint PARALLEL pour cette table, l'optimiseur "jongle" entre le scan classique de D_PRODUCT_PART (ligne du plan 12 et 13 ci-dessus) et le scan parallèle de F_SALES_PART (lignes du plan 13 et 14). La jointure est réalisée en éclatant les résultats du scan de D_PRODUCT part sur différent processus (ligne du plan 10 opération S->p en mode BROADCAST LOCAL).

Pour faire un partition wise join il faudrait utiliser un hint PARALLEL sur la table D_PRODUCT_PART. Mais ce n'est pas suffisant... Il faut aussi spécifier un DOP égal au nombre de partitions/sous-partitions :

Parallélisme et partition wise join
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
SELECT /*+PARALLEL(s 5) PARALLEL(p 5) */cod_typ_pdt, TRUNC(cod_dat,'MM'), SUM(amt_sls) amt_sls, SUM(amt_dsc) amt_dsc
FROM
F_SALES_PART s,
D_PRODUCT_PART p
WHERE 
COD_DAT BETWEEN TO_DATE('2010-05-01','YYYY-MM-DD') AND TO_DATE('2010-05-31','YYYY-MM-DD')
AND s.COD_PDT=p.COD_PDT 
AND s.COD_PDT < '0000000091050'
GROUP BY 
cod_typ_pdt,TRUNC(cod_dat,'MM')
;
 
----------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                         | Name           | ROWS  | Bytes |TempSpc| COST (%CPU)| Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                  |                |   157K|  7687K|       |   815   (4)|       |       |        |      |            |
|   1 |  PX COORDINATOR                   |                |       |       |       |            |       |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)             | :TQ10001       |   157K|  7687K|       |   815   (4)|       |       |  Q1,01 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY                  |                |   157K|  7687K|    19M|   815   (4)|       |       |  Q1,01 | PCWP |            |
|   4 |     PX RECEIVE                    |                |   157K|  7687K|       |   815   (4)|       |       |  Q1,01 | PCWP |            |
|   5 |      PX SEND HASH                 | :TQ10000       |   157K|  7687K|       |   815   (4)|       |       |  Q1,00 | P->P | HASH       |
|   6 |       HASH GROUP BY               |                |   157K|  7687K|    19M|   815   (4)|       |       |  Q1,00 | PCWP |            |
|   7 |        PX PARTITION HASH ALL      |                |   157K|  7687K|       |   810   (3)|     1 |     5 |  Q1,00 | PCWC |            |
|*  8 |         HASH JOIN                 |                |   157K|  7687K|       |   810   (3)|       |       |  Q1,00 | PCWP |            |
|*  9 |          TABLE ACCESS FULL        | D_PRODUCT_PART |  1640 | 27880 |       |     2   (0)|     1 |     5 |  Q1,00 | PCWP |            |
|  10 |          PX PARTITION RANGE SINGLE|                |   172K|  5564K|       |   807   (3)|     3 |     3 |  Q1,00 | PCWC |            |
|* 11 |           TABLE ACCESS FULL       | F_SALES_PART   |   172K|  5564K|       |   807   (3)|    11 |    15 |  Q1,00 | PCWP |            |
----------------------------------------------------------------------------------------------------------------------------------------------
 
-- L'opération de PX PARTITION HASH ALL (ligne 7) au dessus de l'opération de HASH JOIN signale le partition wise join. 

Rentrons plus en détail dans le fonctionnement du parallelisme Oracle:

Fonctionnement du parallélisme

Lorque l'optimiseur à décider d'utiliser le parallelisme, et que le plan est déterminé, le moteur de base de données va instancié un processus le "Query Coordinator".
Ce processus, va créer des sous-processus qui auront tous une partie de la tache de départ à effectuer, c'est lui qui va demander un certain nombre de processus dans le pool de processus.
Les processus vont communiquer entre-eux et avec le QC aux travers de buffers mémoires situés dans la shared pool.Le QC ne réalisera qu'une faible partie du travail, ce sont surtout les sous-processus qui effectue réellement le dur du travail.

Les sous-processus (également appeller parallel server) sont répartis en 2 groupes :

  • Les consommateurs (ce sont les processus qui recoivent l'information)
  • Les producteurs (ce sont les processus qui produisent l'information)

Cas particulier d'un scan

  • Les données sont divisées en en granule qui sont au choix soit :
    • les plages de block : c'est le type de granule que l'on rencontre le plus souvent car il permet d'uniformiser le travail sur tous les processus.
    • des partitions : ce type de granule n'est rencontré que sur des segments partitionnés (option de l'edition entreprise) et si les partitions sont de tailles homogènes
  • Un granule est assigné à un et un seul sous-processus (producteur)
  • L'optimiseur choisi dynamiquement la taille des granules de manière à répartir et équilibrer la charge sur tous les sous-processus. C'est pour cette raison que l'on observe des px block iterator le plus souvent même sur des tables partitionnées car si les partitions ne sont pas homogènes, l'optimiseur préférera réaffecter la charge de manière équitable entre les processus esclaves.
  • Si le nombre de granule est supérieur au nombre de processus escalves alloués, lorsqu'un processus esclave à terminé un granule, un autre granule lui est affecté.

 

Oracle parallelisme scan segment

Un jeu de processus esclaves est coordonnés par le Query Coordinator (QC).

Chaque processus est en charge du scan d'une partie des blocs du segment : un granule.

Si un processus à terminé son granule et qu'il en reste à traiter le processus sera affecté sur un nouveau granule.

Un exemple de plan

pour une requête
SELECT /*+PARALLEL(s 4)*/ * FROM F_SALES s;

------------------------------------------------------------------------------
| Id  | Operation            | Name     | Rows  |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |          |    10M|        |      |            |
|   1 |  PX COORDINATOR      |          |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)| :TQ10000 |    10M|  Q1,00 | P->S | QC (RAND)  |
|   3 |    PX BLOCK ITERATOR |          |    10M|  Q1,00 | PCWC |            |
|   4 |     TABLE ACCESS FULL| F_SALES  |    10M|  Q1,00 | PCWP |            |
------------------------------------------------------------------------------

Autres opérations parallélisables

Oracle est capable de paralléliser d'autres opérations que les scans. Il est capable de paralléliser les opérations de jointure, d'agrégation et de tris ainsi que les opérations d'insertion.

Lorsqu'une requête necessite 2 ou plusieurs opérations, la base de données va utiliser 2 jeux de processus esclaves (scan et jointure par exemple). Il est donc nécessaire de faire communiquer les processus entre eux afin de distribuer les données.

parallelisme_scan_sort.jpg

Un exemple de plan pour ce type d'opération:

SELECT /*+PARALLEL(s 4)*/ count(distinct COD_DAT) from F_SALES;

---------------------------------------------------------------------------
| Id  | Operation                 | Name     |    TQ  |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |          |        |      |            |
|   1 |  SORT GROUP BY            |          |        |      |            |
|   2 |   PX COORDINATOR          |          |        |      |            |
|   3 |    PX SEND QC (RANDOM)    | :TQ10001 |  Q1,01 | P->S | QC (RAND)  |
|   4 |     SORT GROUP BY         |          |  Q1,01 | PCWP |            |
|   5 |      PX RECEIVE           |          |  Q1,01 | PCWP |            |
|   6 |       PX SEND HASH        | :TQ10000 |  Q1,00 | P->P | HASH       |
|   7 |        SORT GROUP BY      |          |  Q1,00 | PCWP |            |
|   8 |         PX BLOCK ITERATOR |          |  Q1,00 | PCWC |            |
|   9 |          TABLE ACCESS FULL| F_SALES  |  Q1,00 | PCWP |            |
---------------------------------------------------------------------------

On appelle parallélisme intra-operation , le parallelisme lié à une seule opération (parallélisme en oeuvre au sein d'un seul jeu de processus)
On appelle parallélisme inter-operation, le parallelisme en oeuvre entre deux jeux de processus esclaves.
Dans l'exemple ci-dessus, le parallélisme intra-operation est mis en oeuvre 2 fois (une fois pour le scan et une autre pour le tri) et la parallélisme inter-operation est mis en oeuvre 1 fois entre les deux jeux de processus.

 Voici les différentes méthodes de redistribution des données (Colonne "PQ Distrib"  dans les plans d'éxécution) :

Méthode Explication
BROADCAST Chaque producteur envoi toutes ses lignes à chaque consommateur
HASH Les producteurs envoi les lignes aux consommateurs en fonction des résultats d'une fonction de hachage. Par exemple,pour les opération de GROUP BY, la fonction de hachage sera appliquée sur les colonnes du regroupement

QC ORDER

Chaque producteur envoi toutes les lignes au coordinateur. L'ordre est important (pour un tri parallel par exemple)
QC RANDOM Chaque producteur envoi toutes les lignes au coordinateur. L'ordre n'est pas important.
RANGE Les producteurs envoient une partie des lignes à différents consommateurs. Les parties sont déterminées dynamiquement à partir des colonnes utilisées dans les opérations (TRI, GROUP BY)
ROUND ROBIN Les producteur envoi chaque ligne à un seul consommateur à la fois. Ainsi les lignes sont redistribuer les lignes de manière équitable sur les consommteurs.

 Voici maintenant les différentes relations possibles entre les opérations parallèles (Colonne IN-OUT dans les plans d'exécution).

Abreviation Nom Signification
P->S Parallel to Serial Une opération parallèle envoi des données vers un opération non-parallèle. Cette relation éxiste toujours pour envoyere les données au QC (Query Coordinator)
P->P Parallel to parallel Une opération parallèle envoi ses données un autre opération réalisée également en parallèle. Cela ce produit lorsqu'il il a deux jeux de processus parallèles.
PCWP Parallel Combined With Parent Un opération qui est exécutée en parallèle par les mêmes processus qui s'executent sur l'opération mère (dans le plan d'exécution). Donc pas de communication (puisque ce sont les mêmes processus)
PCWC Parallel Combined With Child Un opération qui est exécutée en parallèle par les mêmes processus qui s'executent sur l'opération fille (dans le plan d'exécution). Donc pas de communication (puisque ce sont les mêmes processus)
S->P Serial to Parallel un opération non-parallèle envoi ses données vers un opération réalisé en parallèle. Cette opération n'est pas très efficase puisque un seul processus ne pouvant pas être plus rapide que plusieurs, les consommateurs passent leur temps à attendre les données au lieu de travailler.

NB : le dop (degre of parallelism) défini le nombre de processus pour le parallélisme intra-operation. Lorsqu'il y a du parallélisme inter-operation, le nombre de processus utilisés pour éxécuter un requête est le double du dop. En effet seuls 2 jeux de processus peuvent être actif au même moment pour une même requête et car le moteur impose que le dop des 2 jeux soit le même.

Operations interressantes en combinaison avec le parallelisme

Le calcul des statistiques pour l'optimiseur peut être forcé sur un certain dégré de parallelisme ou utiliser le dégré de parallélisme défini sur les objets (tables, index, snapshots...)

Calcul des statistiques en parallèle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
-- Calcul automatique des statistiques pour un schema (EDWH),  le dop étant forcé à 4 pour tous les objets
 
BEGIN
  SYS.DBMS_STATS.GATHER_SCHEMA_STATS (
     OwnName           => 'EDWH'
    ,Granularity       => 'DEFAULT'
    ,Options           => 'GATHER STALE'
    ,Gather_Temp       => FALSE
    ,Estimate_Percent  => SYS.DBMS_STATS.AUTO_SAMPLE_SIZE
    ,Block_sample      => TRUE
    ,Method_Opt        => 'FOR ALL COLUMNS SIZE AUTO '
    ,Degree            => 4
    ,CASCADE           => TRUE
    ,No_Invalidate     => FALSE);
END;
/
 
-- Calcul automatique des statistiques pour un schema (EDWH), le dop étant repris des objets
BEGIN
  SYS.DBMS_STATS.GATHER_SCHEMA_STATS (
     OwnName           => 'EDWH'
    ,Granularity       => 'DEFAULT'
    ,Options           => 'GATHER STALE'
    ,Gather_Temp       => FALSE
    ,Estimate_Percent  => SYS.DBMS_STATS.AUTO_SAMPLE_SIZE
    ,Block_sample      => TRUE
    ,Method_Opt        => 'FOR ALL COLUMNS SIZE AUTO '
    ,Degree            => NULL
    ,CASCADE           => TRUE
    ,No_Invalidate     => FALSE);
END;
/ 

La création ou la reconstruction d'index

Creation d'index avec utilisation du parallelisme
CREATE INDEX EDWH.IX1 ON EDWH.F_SALES_PART (COD_DAT, COD_PDT)  NOLOGGING LOCAL PARALLEL 15;
 
------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                         | Name         | ROWS  | Bytes | COST (%CPU)| Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------------------------
|   0 | CREATE INDEX STATEMENT            |              |  9996K|   209M|  4472   (1)|       |       |        |      |            |
|   1 |  PX COORDINATOR                   |              |       |       |            |       |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)             | :TQ10000     |  9996K|   209M|            |       |       |  Q1,00 | P->S | QC (RAND)  |
|   3 |    PX PARTITION HASH ALL          |              |  9996K|   209M|            |     1 |     5 |  Q1,00 | PCWC |            |
|   4 |     INDEX BUILD NON UNIQUE (LOCAL)| IX1          |       |       |            |     1 |    15 |  Q1,00 | PCWP |            |
|   5 |      SORT CREATE INDEX            |              |  9996K|   209M|            |       |       |  Q1,00 | PCWP |            |
|   6 |       TABLE ACCESS FULL           | F_SALES_PART |  9996K|   209M|  1218   (2)|     1 |    15 |  Q1,00 | PCWP |            |
------------------------------------------------------------------------------------------------------------------------------------
  

La création d'une clef primaire par alter table ne peut pas être réalisée en parallèle directement. Pour pallier à cela il faut créer un index unique sur les colonnes de la PK avec l'option PARALLEL. Une fois l'index unique créé, on peut intégrer la contrainte de clef primaire sur la table.

Création d'une clef primaire en utilisant le parallelisme
-- On procède en deux temps :
CREATE UNIQUE INDEX PK_TAB1 ON Tab1(c1 , c2) PARALLEL 4;
 
ALTER TABLE Tab1 ADD CONSTRAINT PK_Tab1 PRIMARY KEY (c1 , c2);
 
-- L'index PK_TAB1 a été créé en profitant du parallelisme mais il reste avec l'option PARALLEL pour les autres opérations.
-- Il est nécessaire de le modifier pour revenir à un index non parallèle
 
ALTER INDEX PK_TAB1 NOPARALLEL;
  

L'utilisation du parallelisme force Oracle à ne pas utiliser le db_cache (le cache de données). Les données lues depuis les structures (tables, index, snapshots...) sont directement intégrées à la PGA. C'est pour cette raison que lorsqu'on observe les statistiques d'une requête utilisant le parallelisme on observe surtout des Disk_Read et non des Buffer_Gets.

Cela a plusieurs implications :

  • Il est important de ne pas utiliser le parallélisme de manière systématique
  • Il faut éviter de placer des tables de petites tailles avec l'option PARALLEL
  • Seules les grandes tables ou des requêtes bien spécifiques bénéficieront pleinement du parallelisme
  • Vu que les données lues bypassent le cache de données et qu'il est nécessaire pour Oracle de garantir l'intégrité des données, les requêtes parallèles forcent Oracle à effectuer un checkpoint. Cela peut entrainer des problèmes de concurrence sur des environnements ayant beacoup de modification.

Le parallelisme reste donc plutot indiqué pour :

  • les opérations de maintenance (calcul de statistiques, création ou reconstruction d'index),
  • les opérations de chargement massif (Create table as select (CTAS), insert /*+APPEND*/ select)
  • les entrepots de données (infocentre ou datawarehouse c'est selon...) pour les très grandes tables

Pour autoriser les opérations d'insertion en parallèle il est nécessaire de modifier la session :

Modification de la session pour profiter du parallélisme (SELECT et DML)
-- Autoriser les requêtes parallèles (SELECT) 
ALTER SESSION ENABLE PARALLEL QUERY;   
 
-- Autoriser les mises à jours en parallèle (INSERT/UPDATE/MERGE) 
ALTER SESSION ENABLE PARALLEL DML;   
 
-- Retour à la normale en interdisant les mise à jour en parallèle pour la session 
ALTER SESSION DISABLE PARALLEL DML;   

 

Paramètres d'initialisation liés aux parallélisme:

  • parallel_min_servers : nombre de processus esclaces initialement instancié au démarrage de l'instance. Ces processus esclaves sont immédiatement disponibles dès qu'une requête en a besoin. Par défaut ce paramètre est à 0. Les processus esclaves restent en veilles dans le pool pendant 5 minutes puis sont purgés. Il est souvent conseillé de modifier la valeur par défaut pour éviter la surcharge de création initiale.
  • parallel_max_servers : nombre maximum de processus esclaves disponible dans le pool. Par défaut entre 10 fois le nombre de coeurs * le nombre de parallel_threads_per_cpu. (Pour un dual core, avec thread_per_cpu=2 --> 40). Le réglage peut dépendre du type de processeur. Un Power6 ou Power7 pourra encaisser plus qu'un core2 ou un xeon 4coeurs.
  • parallel_automatic_tuning : lorsqu'il est à TRUE, il permet de
    • gérer les "tables queues" dans le large pool plutot que dans le share pool (ce qui est conseillé). Les "tables queues" étant les structures en mémoire utilisées pour les communications inter-operation.
    • modifier certains paramètres et nottament le parallel_execution_message_size qui est par défaut à 2Ko et passe alors à 4Ko
  • parallel_execution_message_size : par défaut à 2K en 10g et 16K en 11g mode datawarehouse. Une taille trop faible engendre des attentes au niveaux des communications entre processus parallèles. Pour de meilleure performances pensez à un passage à 16Ko, 32Ko voir 64Ko si l'OS le permet.

 

Ajouter vos commentaires

Poster un commentaire en tant qu'invité

0 / 30000 Restriction des caractères
Votre texte doit contenir entre 10 et 30000 caractères
Vos commentaires sont soumis à la modération de l'administrateur.
conditions d'utilisation.
  • Aucun commentaire trouvé