Bonjour à tous c'est mon premier message ici!

J'ai un gros souci de performance sur un programme et j'aimerai avoir votre point sur ce qu'il faudrait faire pour que ce soit un peu plus rapide.

J'explique l'algo en faisant simple:

J'ai deux tables :
- une table de données très volumineuse (potentiellement des dizaines d emillions de lignes)- une table de résultat qui synthétise les données (21000 lignes)

Mon programme traite les lignes de ma table de données unes à unes, prend le montant de cette ligne et le décompose sur certaines lignes de ma table de résultat.

Aujourd'hui avec mon programme actuel j'ai créé un curseur sur ma table de données qui balaye toutes les lignes (après les avoir regroupées) et je balaye ensuite les lignes de ma table de résultat qui correspondent à cette ligne de données.
En fait sur le deuxième curseur j'ai un créé un SQL dynamique en fonction de ma ligne de données.
Le deuxième curseur peut contenir entre quelques enregistrements à plusieurs milliers.

Enfin sur chacune des lignes de résultat je fais un calcul et j'update la ligne. Donc en fait je peux faire plusieurs milliers d'update par ligne de ma table de données!

Je mets ci-dessous une partie du code :

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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
 
 
cursor mont_tous_cri is select DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9, SUM(Montant) as montant 
from Tbl_donnees where DC1 is NOT NULL and DC2 is NOT NULL and DC3 is NOT NULL and DC4 is NOT NULL 
and DC5 is NOT NULL and DC6 is NOT NULL and DC7 is NOT NULL and DC8 is NOT NULL and DC9 is NOT NULL GROUP BY DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9;
montant_tout_cri mont_tous_cri%rowtype;
 
for montant_1_CRI in mont_1_CRI loop
 
  demande(1) := montant_1_CRI.DC1;
  if demande(1) is not null then
    cpt_zero := cpt_zero + 1;
    critere1 := ' C1 = '|| demande(1) ;
  end if;
 
  demande(2) :=montant_1_CRI.DC2;
 
  if demande(2) is not null then
    cpt_zero := cpt_zero + 1;
    if cpt_zero = 1 then
      critere1 := ' C2 = '|| demande(2) ;
      else
      critere1 := critere1 || ' and C2 = '|| demande(2) ;
    end if;
  end if;
 
  demande(3) :=montant_1_CRI.DC3;
 
  if demande(3) is not null then
    cpt_zero := cpt_zero + 1;
    if cpt_zero = 1 then
      critere1 := ' C3 = '|| demande(3) ;
      else
      critere1 := critere1 || ' and C3 = '|| demande(3) ;
    end if;
  end if;
 
  demande(4) :=montant_1_CRI.DC4;
 
  if demande(4) is not null then
    cpt_zero := cpt_zero + 1;
    if cpt_zero = 1 then
      critere1 := ' C4 = '|| demande(4) ;
      else
      critere1 := critere1 || ' and C4 = '|| demande(4) ;
    end if;
  end if;
 
  demande(5) :=montant_1_CRI.DC5;
 
  if demande(5) is not null then
    cpt_zero := cpt_zero + 1;
    if cpt_zero = 1 then
      critere1 := ' C5 = '|| demande(5) ;
      else
      critere1 := critere1 || ' and C5 = '|| demande(5) ;
    end if ;
  end if;
 
  demande(6) :=montant_1_CRI.DC6;
 
  if demande(6) is not null then
    cpt_zero := cpt_zero + 1;
    if cpt_zero = 1 then
      critere1 := ' C6 = '|| demande(6) ;
      else
      critere1 := critere1 || ' and C6 = '|| demande(6) ;
    end if;
  end if;
 
  demande(7) :=montant_1_CRI.DC7;
 
  if demande(7) is not null then
    cpt_zero := cpt_zero + 1;
    if cpt_zero = 1 then
      critere1 := ' C7 = '|| demande(7) ;
      else
      critere1 := critere1 || ' and C7 = '|| demande(7) ;
    end if; 
  end if;
 
  demande(8) :=montant_1_CRI.DC8;
 
  if demande(8) is not null then
    cpt_zero := cpt_zero + 1;
    if cpt_zero = 1 then
      critere1 := ' C8 = '|| demande(8) ;
      else
      critere1 := critere1 || ' and C8 = '|| demande(8) ;
    end if;
  end if;
 
  demande(9) :=montant_1_CRI.DC9;
 
  if demande(9) is not null then
    cpt_zero := cpt_zero + 1;
    if cpt_zero = 1 then
      critere1 := ' C9 = '|| demande(9) ;
      else
      critere1 := critere1 || ' and C9 = '|| demande(9);
    end if;
  end if;
 
  sum_montant := montant_1_CRI.montant;
  strsql := 'select * from VW_TBL_RES_UTILE where' || critere1 || '';
 
  open c_cur for strsql;
  loop
    fetch c_cur into C_final;
    exit when c_cur%notfound;
    res(1) :=C_final.C1;
    res(2) :=C_final.C2;
    res(3) :=C_final.C3;
    res(4) :=C_final.C4;
    res(5) :=C_final.C5;
    res(6) :=C_final.C6;
    res(7) :=C_final.C7;
    res(8) :=C_final.C8;
    res(9) :=C_final.C9;
    pres_donnes :=C_final.pres_donnees;
    montant1CRI :=C_final.montant;
 
    montant_tot_CRI := pres_donnes / nombre * sum_montant;
    montant_tot2 := montant_tot_CRI + montant1CRI;
 
    UPDATE Tbl_res set Tbl_res.montant = montant_tot2 where C1 = offre(1)  and C2 = offre(2) and C3 = offre(3) and C4 = offre(4) 
    and C5 = offre(5) and C6 = offre(6) and C7 = offre(7) and C8 = offre(8) and C9 = offre(9);
 
  end loop;
  close c_cur;
  -- mise à zero des donnees
  cpt_zero := 0;
  critere1 := '';
end loop;
Bref pour traiter 10000 lignes mon programme met 27 min. C'est juste horrible.
De mon avis de profane avec de faibles connaissances en architecture il me semble que faire pleins d'updates ralentit considérablement les perfs car on écrit des données à chaque fois.Ou alors est ce que c'est le fait d'utiliser deux curseurs imbriqués?
Est ce que ce ne serait pas mieux de passer par un tableau de valeurs ou par une table temporaire gérée uniquement en mémoire?
J'alimente ma table au fur et à mesure du code puis je fais un update juste à la fin du programme.

Si vous avez des idées d'amélioration je suis preneur de toute information!

Merci d'avance pour vos lumières!