Bonjour, j'ai une requête "UPDATE" qui tape dans deux tables moyennement volumineuses, et qui met un temps fou (plus de 15 minutes) pour mettre à jour à peine une dizaine de lignes...
SGBD : Oracle 8.1.7
Structure des tables impactées :
PRO :
Table des produits
24424 lignes (3214 avec CODSOC = 2)
Champs :
CODSOC : code société
CODPRO : code produit
...
CODZN15 : champ libre varchar2, contenant une date au format "YYYYMMDD" ou " " si vide (un espace)
clé primaire : CODSOC, CODPRO
index que je viens de créer : (pas très utile, parceque un count(*) pour CODSOC = 2 and CODZN15 = ' ' retournait 37 en 0,6 secondes)
Code :
- CREATE INDEX WI_PROZN15 ON PRO
- (CODSOC, CODZN15)
- LOGGING
- TABLESPACE IDXGNX1
- PCTFREE 10
- INITRANS 2
- MAXTRANS 255
- STORAGE (
- INITIAL 24K
- NEXT 192K
- MINEXTENTS 1
- MAXEXTENTS 120
- PCTINCREASE 10
- FREELISTS 1
- FREELIST GROUPS 1
- BUFFER_POOL DEFAULT
- )
- NOPARALLEL;
|
EVE :
Table des évènements
187570 lignes (186327 avec CODSOC = 2)
Champs :
CODSOC : code société
ACHVTE : Achat/Vente (flag)
TYPEVE : Type d'évènement (commande, devis, livraison, etc.)
NUMEVE : Numéro d'évènement
...
DATEVE : Date de l'évènement
CODETA : Statut de l'évènement
clé primaire : CODSOC, ACHVTE, TYPEVE, NUMEVE
EVP :
Table des postes des évènements (lignes)
494172 lignes (484530 avec CODSOC = 2)
Champs :
CODSOC : code société
ACHVTE : Achat/Vente (flag)
TYPEVE : Type d'évènement (commande, devis, livraison, etc.)
NUMEVE : Numéro d'évènement
NUMPOS : Numéro de ligne du poste
...
CODPRO : Code produit
clé primaire : CODSOC, ACHVTE, TYPEVE, NUMEVE, NUMPOS
index utile : CODSOC, ACHVTE, TYPEVE, NUMEVE, CODPRO
EVL :
Table des sous-postes des évènements (ventillation datées)
498399 lignes (488706 avec CODSOC = 2)
Champs :
CODSOC : code société
ACHVTE : Achat/Vente (flag)
TYPEVE : Type d'évènement (commande, devis, livraison, etc.)
NUMEVE : Numéro d'évènement
NUMPOS : Numéro de ligne du poste
NUMLIG : Numéro de ligne du sous-poste
...
CODPRO : Code produit
clé primaire : CODSOC, ACHVTE, TYPEVE, NUMEVE, NUMPOS, NUMLIG
index utile : CODSOC, ACHVTE, TYPEVE, NUMEVE, CODPRO
Ce que doit faire la requête :
Mettre à jour le champ CODZN15 de PRO avec la date de la première commande passée sur ce produit
Critères :
CODSOC = 2 (société qui utilise ce champ)
ACHVTE = 'V' (vente)
TYPEVE = 'CDV' (Commande de vente)
CODETA = 'V', 'S', 'I' (Validé, Soldé ou Incident -c'est pas parcequ'on a un problème avec la commande que le produit n'a pas été commandé-)
CODZN15 = ' ' (Si le produit a déjà été commandé avant, ça sert à rien de retrouver la date)
La requête originale :
Code :
- update pro set codzn15= (select
- nvl(min(eve.dateve),' ')
- from
- evl,eve
- where
- eve.codsoc=2
- and eve.achvte='V'
- and eve.typeve='CDV'
- and (eve.codeta='V' or eve.codeta='S' or eve.codeta='I')
- --
- and evl.codsoc=eve.codsoc
- and evl.achvte=eve.achvte
- and evl.typeve=eve.typeve
- and evl.numeve=eve.numeve
- and evl.codpro=pro.codpro)
- where
- codsoc=2
- and codzn15=' ';
|
A priori, passer par EVL ne sert à rien, puisque :
1) Un cadencement d'un poste ne peux pas porter sur un produit différent que le poste dont il est issu
2) La société ne fait de toute façon pas de cadancement
3) On récupère la date de la commande, pas celle du cadancement
4) EVL est plus volumineuse que EVP sans apporter plus d'infos dans notre cas
J'ai donc modifié la requête :
Code :
- update pro set codzn15= (select
- nvl(min(eve.dateve),' ')
- from
- evp,eve
- where
- eve.codsoc=2
- and eve.achvte='V'
- and eve.typeve='CDV'
- and (eve.codeta='V' or eve.codeta='S' or eve.codeta='I')
- --
- and evp.codsoc=eve.codsoc
- and evp.achvte=eve.achvte
- and evp.typeve=eve.typeve
- and evp.numeve=eve.numeve
- and evp.codpro=pro.codpro)
- where
- codsoc=2
- and codzn15=' ';
|
En gros, avec création de l'index et changement de la requête, je suis passé de...
Un temps interminable qui se termine par un rollback à... là même chose.
Pourtant, y'a que 37 lignes à mettre à jour !
Dans le doute, l'autre jour j'ai profité de la nuit pour rebooter le server, il n'y a donc pas de lock dans la base.
L'outil qui utilise la base, pourtant lourdement consommateur en requêtes, travaille très vite, donc ce n'est pas non plus un problème de performances du serveur.
Et là je sèche un peu, je sais pas trop quoi faire pour améliorer la chose.
Je pourrais rajouter une clause WHERE dans ma requête pour ne chercher la date de première commande que pour les produits qui ont été commandés, mais vu qu'il n'y a en tout que 37 lignes (et ça fait une semaine que ça n'a pas tourné !) je doute que ça change quoi que ce soit...