Bonjour,
Je viens de récupérer un série de "moulinettes" à optimiser car les données vont être multiplié selon les tables de 2 à 26 000 avec des problèmes de performances. J'ai optimisé tout sauf 4, procédure qui ont la même structure. Le but de ces dernières "moulinettes" est de transformer des lignes contenant un état et date d'effet en ligne contenant un état et date de début et une date de fin. Les états sont A(ctif) et I(nactif).
Pour être honnête, je ne sais pas pour quel bout prendre pour optimiser cela, en sachant que je ne connais peu Oracle (beaucoup plus SQLServer, MySQL et SQLite)
Je met le code (je l'ai modifié pour qu'il soit généraliste, je ne l'ai pas testé) :
Je suis preneur de toute idée ...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 create or replace PROCEDURE "TRAITEMENT_XXXXXX" AS BEGIN DECLARE v_cpt NUMBER := 0; -- permettra de compter les lignes déjà insérées pour un Code donné r_recent TABLE_DESTINATION%ROWTYPE ; BEGIN -- on purge la table d'export DELETE FROM TABLE_DESTINATION; -- on boucle sur toutes les lignes triées par code et par date_effet FOR item IN ( SELECT * FROM TABLE_SOURCE ORDER BY Code,date_effet ) LOOP -- gestion du A IF item.STATUT = 'A' THEN BEGIN -- requête récupérant la ligne dont le début est le plus récent SELECT * INTO r_recent FROM TABLE_DESTINATION WHERE Code = item.Code AND DATEDEBUT = ( SELECT max(TD.DATEDEBUT) FROM TABLE_DESTINATION TD WHERE TD.Code = item.Code ); -- si l'élément considéré est postérieur à l'élément en export le plus récent IF item.DATE_EFFET > r_recent.DATEDEBUT THEN -- Si l'élément le plus récent n'est pas inactivé, on l'inactive... IF r_recent.DATEFIN IS NULL THEN -- UPDATE la date de fin et les descriptions UPDATE TABLE_DESTINATION SET DATEFIN = item.DATE_EFFET WHERE Code = item.Code AND DATEDEBUT = r_recent.DATEDEBUT; END IF; -- ... puis on insère une nouvelle ligne avec datedebut = date_effet INSERT INTO TABLE_DESTINATION (CODE, DESTRA, DATEDEBUT, DATEFIN) VALUES ( item.Code, item.DESC_LONGUE, item.DATE_EFFET, ''); ELSE NULL; END IF; EXCEPTION WHEN NO_DATA_FOUND THEN -- Ce dode n'existe pas encore dans la base, il faut donc l'inserer INSERT INTO TABLE_DESTINATION (CCE, DESTRA, SHOTRA, ENAFLG, IPT, DIENBR, OTHDIE0, DEFCCE0, FCY, DATEDEBUT, DATEFIN) VALUES ( item.Code, item.DESC_LONGUE, item.DATE_EFFET, ''); END; -- gestion du I ELSIF item.STATUT = 'I' THEN BEGIN -- lire la dernière ligne FARO la plus récente SELECT * INTO r_recent FROM TABLE_DESTINATION WHERE Code = item.Code AND DATEDEBUT = ( SELECT max(TB.DATEDEBUT) FROM TABLE_DESTINATION TB WHERE TB.Code = item.Code ); -- ce select retourne une exception NO_DATA_FOUND si il ne retourne aucune ligne IF r_recent.DATEFIN IS NULL THEN -- la dernière ligne FARO la plus récente est encore active... UPDATE TABLE_DESTINATION SET DATEFIN = item.DATE_EFFET WHERE Code = item.Code AND DATEDEBUT = r_recent.DATEDEBUT; ELSE -- la dernière ligne la plus récente est déjà inactivée, on l'ignore NULL; END IF; EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END; -- fin du I ELSE -- erreur sur le statut (ni I , ni A) -- Trace END IF; END LOOP; END; END;
Partager