J'ai une requête traitant 2 tables avec plus de 61 millions d'enregistrements chacune.Optimisation des performances d'une requête traitant des millions de lignes
- WB_YH_BCUPDATE_FULL_BASE: table contenant les clients et tous les mois, ils étaient actifs. (de 2014 à maintenant)
CUSTOMERNUMBER | MOIS DE LA VOITURE
99999 | 201401
99999 | 201402
99999 | 201403
....
- WB_YH_BCUPDATE_MATCH_MONTH: table contenant les clients et tous les mois qui étaient actifs avec + un champ supplémentaire contenant les CAR_MONTH fictive + 6 mois.
CUSTOMERNUMBER | CAR_MONTH | MATCH_MONTH_6
99999 | 201401 | 201407
99999 | 201402 | 201408
99999 | 201403 | 201409
...
Maintenant, je veux vérifier tous les clients et tous leurs correspondants CAR_MONTHS si elles étaient encore actifs (= ils apparaissent dans le tableau) après 6 mois. Pour cela, je dois utiliser le champ que j'ai créé, étant MATCH_MONTH_6.
J'utilise la requête suivante:
select distinct a.CUSTOMERNUMBER
, a.CAR_MONTH
, b.MATCH_MONTH_6
, CASE WHEN b.CUSTOMERNUMBER is null then 0
ELSE 1
END FL_MATCH_6
from WB_YH_BCUPDATE_FULL_BASE a left join WB_YH_BCUPDATE_MATCH_MONTH b
on a.CUSTOMERNUMBER = b.CUSTOMERNUMBER
and a.CAR_MONTH = b.CAR_MONTH
and b.MATCH_MONTH_6 in (
select CAR_MONTH
from WB_YH_BCUPDATE_FULL_BASE
where customernumber = a.customernumber
);
La performance de ma requête est vraiment pauvre comme vous pouvez le voir dans le plan d'exécution suivant:
Plan Hash Value : 3376431373
-----------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
-----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 25897713 | 673340538 | 371846479 | 02:56:04 |
| 1 | HASH UNIQUE | | 25897713 | 673340538 | 371846479 | 02:56:04 |
| 2 | NESTED LOOPS OUTER | | 61874441 | 1608735466 | 371674345 | 02:55:59 |
| 3 | TABLE ACCESS STORAGE FULL | WB_YH_BCUPDATE_FULL_BASE | 61874441 | 742493292 | 3225 | 00:00:01 |
| 4 | VIEW | | 1 | 14 | 6 | 00:00:01 |
| 5 | NESTED LOOPS | | 1 | 31 | 6 | 00:00:01 |
| 6 | NESTED LOOPS | | 24 | 31 | 6 | 00:00:01 |
| * 7 | TABLE ACCESS BY INDEX ROWID | WB_YH_BCUPDATE_MATCH_MONTH | 1 | 19 | 3 | 00:00:01 |
| * 8 | INDEX RANGE SCAN | WB_YH_BCUPDATE_MATCH_MONTH_IND | 24 | | 2 | 00:00:01 |
| * 9 | INDEX RANGE SCAN | WB_YH_BCUPDATE_FULL_BASE_IND | 24 | | 2 | 00:00:01 |
| * 10 | TABLE ACCESS BY INDEX ROWID | WB_YH_BCUPDATE_FULL_BASE | 1 | 12 | 3 | 00:00:01 |
-----------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 7 - filter("A"."CAR_MONTH"="B"."CAR_MONTH")
* 8 - access("A"."CUSTOMERNUMBER"="B"."CUSTOMERNUMBER")
* 9 - access("CUSTOMERNUMBER"="A"."CUSTOMERNUMBER")
* 10 - filter("CAR_MONTH"=TO_NUMBER("B"."MATCH_MONTH_6"))
Avez-vous les gars avez une idée sur comment je peux optimiser cette requête ou comment je peux réécrire cette requête pour être plus performant?
Cordialement,
Vous avez besoin d'index sur les tables. Les conditions "join" sont un bon point de départ. –
Donc 'WB_YH_BCUPDATE_MATCH_MONTH' contient les mêmes données que' WB_YH_BCUPDATE_FULL_BASE', mais avec une colonne supplémentaire? – SQB
J'ai des index sur les deux tables sur le champ CUSTOMERNUMBER. Et @SQB; C'est exact, mais je n'ai pas réussi à obtenir les résultats d'une autre manière sans dupliquer les données dans 2 tableaux. – wbaeckelmans