Bonjour,

J'ai plus ou moins cette situation:
Mon programme parcourt plein plein plein de fois la même table pour récupérer une valeur sur laquelle il y a un index.
Et il connait avant de faire le select, l'ensemble des valeurs qu'il va devoir récupérer.
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
drop table tmp2;
drop table tmp2_temporary;
 
 
CREATE TABLE tmp2 AS (SELECT level AS n, lpad(level,8,'x') AS data FROM dual connect BY level<=100000);
CREATE INDEX tmp2_ind ON tmp2(n,data);
 
PROMPT ============
PROMPT test1
declare
   l_s tmp2.data%type;
begin
   for i in 1..100000 loop
      select data into l_s from tmp2 where n=trunc(dbms_random.value(1,1000));
   end loop;
end;
/
En utilisant un tableau, on gagne du temps, c'est toujours ca de pris mais ce n'est toujours pas fantastique.
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
PROMPT ============
PROMPT test2
declare
 type  t_num is table of number;
   a t_num:=t_num();
   l_s tmp2.data%type;
begin
   for i in 1..100000 loop
      a.extend;
      a(i):=trunc(dbms_random.value(1,1000));
   end loop;
 
   for i in a.first..a.last loop
      select data into l_s from tmp2 where n=a(i);
   end loop;
end;
/
Mais ce n'est pas hyper rapide. Enfin, disons qu'en utilisant une table temporaire qui va contenir toutes mes valeurs random je gagne beaucoup de temps:
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
 
PROMPT ============
PROMPT test3
create global temporary table tmp2_temporary (n2 number);
declare
   type t_num is table of number;
   a t_num:=t_num();
   type t_data is table of tmp2.data%type;
   l_s t_data;
begin
   for i in 1..100000 loop
      a.extend;
      a(i):=trunc(dbms_random.value(1,1000));
   end loop;
   forall i in a.first..a.last insert into tmp2_temporary values (a(i));
   select data bulk collect into  l_s from tmp2 inner join tmp2_temporary on n=n2;
   dbms_output.put_line(l_s.count);
end;
/
Citation Envoyé par Resultats
test1
PL/SQL procedure successfully completed.
Elapsed: 00:00:05.13

test2
PL/SQL procedure successfully completed.
Elapsed: 00:00:03.09

test3
Table created.
Elapsed: 00:00:00.00
100000
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.32
Par contre, je n'ai pas très envie d'utiliser une table temporaire. Psychologiquement ca me bloque.
Mais comme c'est quand même un ordre de grandeur plus rapide que mes autres solutions...

Auriez-vous une idée pour faire la même chose sans la table temporaire ?
Parce que que concrètement, c'est plus rapide avec la table simplement grâce au bulk collect, mais je ne trouve pas d'idée pour utiliser le bulk collect sans la table temporaire.

Genre un equivalent de forall mais avec un select?