Bonjour,
J'ai une requête qui, après migration, est devenue extrêmement lente.
Je ne saurais exactement vous dire de quelle version à quelle version...
10g vers 19c il me semble... et l'application passe par un client 12c. C'est un peu le bordel, et je n'ai pas accès aux serveurs pour vérifier.
J'ai une requête qui fait peu ou prou ça :
Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 var p1 number; var p2 number; exec :p1 := 20181129; exec :p2 := 600064; SELECT * FROM CRM_KM KM WHERE EXISTS ( SELECT * FROM CRM_A1 A1 WHERE A1.ID_KM_250 = KM.ID AND ((cast(NEU / 1000000000 as int) = :p1 AND CRM_RkzPart(4200, RKZ) = :p2) OR (cast(UPD / 1000000000 as int) = :p1 AND CRM_RkzPart(4204, RKZ) = :p2)) );
La colonne "RKZ" de CRM_A1 est un RAW(30) et par conséquent la fonction CRM_RkzPart() pas franchement véloce et non indexable.
Je pense que le souci vient de là : lire NEU et UPD qui sont des entiers, et les diviser par 1000000000 avant de filtrer dessus, c'est pas top non plus.
Pourquoi c'était super rapide avant et super lent maintenant, si quelqu'un à une idée sortie du chapeau je suis preneur, sinon je vais me contenter d'essayer d'améliorer ça.
Je peux par exemple créer une vue (je ne peux pas modifier les tables existantes) qui simplifie les choses :
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 create materialized view V_A1_EXT (ID, DTE, USR) REFRESH force start with (sysdate) next (sysdate+1/1440) with PRIMARY KEY as select ID, cast(NEU / 1000000000 as int), CRM_RkzPart(4200, RKZ) from CRM_A1 where NEU >= TO_NUMBER(TO_CHAR(sysdate, 'YYYYMMDD')) * 1000000000 union all select ID, cast(UPD / 1000000000 as int), CRM_RkzPart(4204, RKZ) from CRM_A1 where UPD >= TO_NUMBER(TO_CHAR(sysdate, 'YYYYMMDD')) * 1000000000;
Et ainsi faire évoluer la requête comme suit :
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 SELECT * FROM CRM_KM KM WHERE EXISTS ( SELECT * FROM CRM_A1 A1 WHERE A1.ID_KM_250 = KM.ID AND EXISTS ( SELECT * FROM V_A1_EXT A1e WHERE A1e.ID = A1.ID AND ((A1e.NEU = :p1 AND A1e.NEU_ID = :p2) OR (A1e.UPD = :p1 AND A1e.UPD = :p2)) ) );
A votre avis, ça peut faire le taf ?
D'autres solutions pour améliorer la chose ?
Partager