[Performance] Select avec trois grosses tables
Bonjour à tous,
Je vous embête un peu parce que j'ai un problème de performance avec un select qui dure 3h. Je suis pas très doué en optimisation et du coup je bloque un peu.
Mon select se base sur 2 tables et 1 vue.
La première table (table a) possède une volumétrie de 2millions de lignes
la seconde table (table b) est petite (11 000 lignes)
la vue est une vue assez simple et rapide à lire (table c) (20 000 lignes)
Afin d'améliorer les performances du select, j'ai crée des index sur mes table :
ma table b (index 1 : ALTACCT,TYPE index 2 : b.CNP_ACCT_MAGN, b.DESCR index 3 :CNP_ACCT_MAGN)
sur ma table A j'ai crée également 4 index (index 1 : ALTACCT,PRODUCT index2 : CNP_MEGA_ENTITE,FISCAL_YEAR, ACCOUNTING_PERIOD, ALTACCT index 3 : ALTACCT et index 4 : PRODUCT)
Le hic c'est que j'ai toujours un full scan sur ma table a que je n'arrive pas à optimiser. Du coup je pense que le trois heures est du à ce full scan.
Ma question est donc :
Est-il possible d’éviter un full scan sur ma table A ?
Le SQL en question le voici
Code:
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
|
SELECT 'TRIM_RBEV1'
a.cnp_mega_entite
a.fiscal_year, a.accounting_period, a.altacct, b.cnp_acct_magn,
b.descr, -SUM (a.amount)
FROM ps_cnp_smldg_t28 a, ps_cnp_cpt_magn b, ps_cnp_prdct_nm_vw c
WHERE b.altacct = a.altacct
AND b.TYPE = 'P'
AND a.product = c.product(+)
AND ( b.cnp_acct_magn = (SELECT d.cnp_acct_magn FROM ps_cnp_norm_magn d WHERE d.cnp_norm = NVL (c.cnp_norm, 'IFRS4')
AND d.cnp_acct_magn = b.cnp_acct_magn)
OR NOT EXISTS (SELECT 'X'
FROM ps_cnp_norm_magn d
WHERE b.cnp_acct_magn = d.cnp_acct_magn))
AND NOT EXISTS (SELECT 1
FROM ps_cnp_cpt_magn
WHERE altacct = a.altacct AND TYPE = 'A')
GROUP BY a.cnp_mega_entite,
a.fiscal_year,
a.accounting_period,
a.altacct,
b.cnp_acct_magn,
b.descr
HAVING SUM (a.amount) >=
0 ; |
Pour plus de lisibilité j'ai mis mon plan d’exécution dans le second message plus bas
Pour info je suis sous oracle 10.2.0.1.0
Auriez vous une piste vers laquelle je puisse m'orienter ?
Merci beaucoup pour votre attention .
le NOT EXISTS rend les requêtes trop lentes à l'execution
Je te proposerais d'utiliser un INTERSECT afin de supprimer les données que tu ne souhaites pas apparaitre dans la requête. Je te proposerais une autres requête mais je ne comprends pas très bien ce que tu souhaites.
J'ai eu une expérience similaire en voulant (cas d'opérateur téléphonique) sélectionner pour un jeu téléphonique tous les numéros (plus de 4millions) sauf ceux des employés. il a fait plus de 2 heures. Un intersect à fait moins de 2 minutes!
Bon je réfléchis à ta requête et je te fais signe.