Question

Dans mon application, je dois ajouter de nombreux enregistrements. J'utilise la construction suivante:

   INSERT /*+ append parallel(t1, 4) parallel(t2, 4) */ ALL
   INTO t1 (col1, col2, col3) VALUES ('val1_1', 'val1_2', 'val1_3')
   INTO t2 (col1, col2, col3) VALUES ('val2_1', 'val2_2', 'val2_3')
   INTO t2 (col1, col2, col3) VALUES ('val3_1', 'val3_2', 'val3_3')
   .
   .
   .
SELECT 1 FROM DUAL;

J'utilise également des conseils d'ajout et parallèles. Notez que j'inserte des données dans deux tables différentes. Il semble que le parallèle soit ignoré (le DBA m'a dit). Alors, comment puis-je savoir s'il est utilisé ou non? Est-il possible d'utiliser un indice parallèle dans une telle construction? Est-ce efficace?

Était-ce utile?

La solution

Ce sera probablement suffisant pour le faire fonctionner:

alter session enable parallel dml;

Vous pouvez vérifier le degré réel de parallélisme avec une requête comme celle-ci:

select px_servers_executions, v$sql.*
from v$sql where lower(sql_text) like '%insert%parallel%' order by last_load_time desc;

Si vous n'obtenez toujours pas de parallélisme, il y a de nombreuses raisons possibles. Pour commencer, regardez ces paramètres:

select * from v$parameter where name like 'parallel%'

Mais vous ne voulez probablement pas de parallélisme pour votre déclaration d'insertion. Le parallélisme a une grande quantité de frais généraux et n'est généralement utile que si vous avez affaire à plusieurs milliers ou millions de dossiers.

Je suppose que votre vrai problème est le moment d'analyser la grande déclaration SQL. Les inserts multiples sont particulièrement mauvais. Si vous essayez d'insérer plus de quelques centaines de lignes, votre requête prendra plusieurs secondes pour l'analyse. Et selon votre version d'Oracle, il ne s'accrochera pas pour toujours si vous essayez d'utiliser 501 tables. Il est beaucoup plus rapide d'exécuter plusieurs petites requêtes au lieu d'une grande requête. Par exemple, 5 inserts de 100 lignes fonctionneront beaucoup plus rapidement qu'un insert de 500 lignes. (En général, c'est exactement l'opposé de la façon de les performances de Tourn pour Oracle. Il s'agit d'un cas spécial en raison des bogues liés à l'analyse de grandes instructions SQL.)

Autres conseils

La Indice n'est pris en charge qu'avec la syntaxe de sous-requête de l'instruction INSERT, pas la clause VALEUR. Si vous spécifiez l'indice d'ajout avec la clause VALEURS, il est ignoré et l'insert conventionnel sera utilisé. Pour utiliser l'insert direct de Path avec la clause VALEURS, reportez-vous à "APPEND_VALUES HINT".

Il y a des cas où le parallélisme est désactivé. Y compris à partir duDocumentation Oracle:

Le parallélisme est désactivé pour les opérations DML sur les tables sur lesquelles vous avez défini une contrainte d'intégrité de déclenchement ou référentielle.

Ce qui me semble une assez grande restriction. Avez-vous un déclencheur ou une clé étrangère sur vos tables?

Activer le parallélisme pour 30 enregistrements serait un gaspillage de ressources. Le parallélisme implique une surcharge coûteuse (travail de fractionnement, attribuant des processus, synchronisant les résultats ...) qui ne valaient pas le coût d'une si petite opération.

Je suppose que vous exécutez cette déclaration des millions de fois si vous souhaitez l'optimiser si mal. Dans ce cas, il serait probablement plus efficace de trouver un moyen de transformer ces millions de déclarations en grandes opérations de sets - qui pourraient bien profiter du parallélisme.


Mise à jour: Une autre idée pourrait être d'exécuter les instructions avec plus d'une session, mettant efficacement la mise en œuvre du parallélisme DIY. Pouvez-vous concevoir votre processus pour que plus d'une session lise les données d'entrée et insérer en même temps?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top