web-dev-qa-db-fra.com

Oracle 11g - Comment optimiser la sélection d'insertion parallèle lente?

nous voulons accélérer l'exécution de l'instruction d'insertion parallèle ci-dessous. Nous prévoyons d'insérer environ 80 millions de disques et leur exécution prend environ 2 heures.

INSERT /*+ PARALLEL(STAGING_EX,16) APPEND NOLOGGING */ INTO STAGING_EX (ID, TRAN_DT, 
RECON_DT_START, RECON_DT_END, RECON_CONFIG_ID, RECON_PM_ID) 
SELECT /*+PARALLEL(PM,16) */ SEQ_RESULT_ID.nextval, sysdate, sysdate, sysdate, 
'8a038312403e859201405245eed00c42', T1.ID FROM PM T1 WHERE STATUS = 1 and not 
exists(select 1 from RESULT where T1.ID = RECON_PM_ID and CREATE_DT >= sysdate - 60) and 
UPLOAD_DT >= sysdate - 1 and (FUND_SRC_TYPE = :1) 

Nous pensons que la mise en cache des résultats de la colonne no exist accélérera les insertions. Comment effectuons-nous la mise en cache? Des idées comment autrement accélérer l'insert?

Veuillez voir ci-dessous les statistiques de planification d’Enterprise Manager. Nous avons également remarqué que les déclarations ne sont pas exécutées en parallèle. Est-ce normal?

insert-select plan statistics from Oracle em

Edit: d'ailleurs, la séquence est déjà mise en cache sur 1M

9
user1928162

Essayez d’utiliser davantage de variables de liaison, en particulier là où des boucles imbriquées peuvent se produire. J'ai remarqué que vous pouvez l'utiliser dans des cas comme

CREATE_DT >= :YOUR_DATE instead of CREATE_DT >= sysdate - 60 

Je pense que cela expliquerait pourquoi vous avez 180 millions d’exécutions dans la partie la plus basse de votre plan d’exécution, alors que l’autre partie de la requête de mise à jour est toujours à 8 millions sur vos 79 millions.

3
Avias

Améliorer les statistiques. Le nombre estimé de lignes est 1, mais le nombre réel de lignes est supérieur à 7 millions. Cela oblige le plan d'exécution à utiliser une boucle imbriquée au lieu d'une jointure de hachage. Une boucle imbriquée fonctionne mieux pour de petites quantités de données et une jointure de hachage fonctionne mieux pour de grandes quantités de données. Cela peut être aussi simple que de s’assurer que les tableaux pertinents contiennent des statistiques précises et à jour. Cela peut généralement être effectué en collectant des statistiques avec les paramètres par défaut, par exemple: exec dbms_stats.gather_table_stats('SIRS_UATC1', 'TBL_RECON_PM');.

Si cela n'améliore pas l'estimation de cardinalité, essayez d'utiliser un indice d'échantillonnage dynamique, tel que /*+ dynamic_sampling(5) */. Pour une requête aussi longue, il vaut la peine de passer un peu de temps supplémentaire aux données d'échantillonnage initiales si cela permet d'améliorer le plan.

Utilisez un parallélisme au niveau instruction au lieu d'un parallélisme au niveau objet. C'est probablement l'erreur la plus courante avec le SQL parallèle. Si vous utilisez un parallélisme au niveau de l'objet, le conseil doit référencer le alias de l'objet. Depuis 11gR2, vous n'avez plus à vous soucier de spécifier des objets. Cette déclaration n'a besoin que d'un seul indice: INSERT /*+ PARALLEL(16) APPEND */ .... Notez que NOLOGGING n'est pas un indice réel.

5
Jon Heller

Je peux voir 2 gros problèmes:

1 - indice parallèle (dans select) NO PAS fonctionne, car il devrait être ainsi + PARALLEL (T1,16)

2 - SELECT NE PAS optimal, il serait préférable d’éviter les expressions NON IN

0
usergray