Envoyé par
ccaye
Donc je supprimais mes enregistrements un par un. Cela peut paraître peu performant, mais comme je désactivais les contraintes et que je sélectionnais sur la clé primaire, le temps de réponse était bien meilleur que pour des suppressions "ensemblistes".
Ça me paraît fallacieux comme argument, ou au moins à fortement nuancer.
La suppression ensembliste profitera des mêmes bénéfices de désactivation des contraintes, et la suppression via la clef primaire si elle nécessite un premier select je ne vois pas pourquoi elle serait beaucoup plus rapide.
Démonstration avec un test simple, une table d'un million de lignes :
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
| create table t1
(
col1 number(10) not null,
col2 number(10) not null,
constraint pk_t1
primary key (col1)
);
insert /*+ APPEND */ into t1 (col1, col2)
select level, level
from dual
connect by level <= 1e6;
commit;
begin
dbms_stats.gather_table_stats
( ownname => user
, tabname => 'T1'
, estimate_percent => 100
, cascade => true
, degree => 4
);
end;
/
create table t1_tmp (col1 number(10)); |
Je vais faire trois simulations, une où on supprime 1% de la table, puis 15%, puis 50%.
J'utilise un modulo sur la seconde colonne comme critère de choix.
On compare votre méthode et le delete ensembliste de base :
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
| declare
v$_compteur pls_integer default 0;
v$_time pls_integer;
begin
dbms_output.put_line('Scénario 1%');
v$_time := dbms_utility.get_time();
execute immediate 'truncate table t1_tmp';
insert into t1_tmp (col1) select col1 from t1 where mod(col2, 100) = 0;
for c in (select col1 from t1_tmp)
loop
delete from t1 where t1.col1 = c.col1;
v$_compteur := v$_compteur +1;
if v$_compteur = 50000 then
-- commit;
v$_compteur := 0;
end if;
end loop;
dbms_output.put_line(' - Méthode TMP + PL/SQL : ' || to_char(dbms_utility.get_time() - v$_time));
rollback;
v$_time := dbms_utility.get_time();
delete from t1 where mod(col2, 100) = 0;
dbms_output.put_line(' - Méthode ensembliste : ' || to_char(dbms_utility.get_time() - v$_time));
rollback;
dbms_output.put_line('Scénario 15%');
v$_time := dbms_utility.get_time();
execute immediate 'truncate table t1_tmp';
insert into t1_tmp (col1) select col1 from t1 where mod(col2, 7) = 0;
for c in (select col1 from t1_tmp)
loop
delete from t1 where t1.col1 = c.col1;
v$_compteur := v$_compteur +1;
if v$_compteur = 50000 then
-- commit;
v$_compteur := 0;
end if;
end loop;
dbms_output.put_line(' - Méthode TMP + PL/SQL : ' || to_char(dbms_utility.get_time() - v$_time));
rollback;
v$_time := dbms_utility.get_time();
delete from t1 where mod(col2, 7) = 0;
dbms_output.put_line(' - Méthode ensembliste : ' || to_char(dbms_utility.get_time() - v$_time));
rollback;
dbms_output.put_line('Scénario 50%');
v$_time := dbms_utility.get_time();
execute immediate 'truncate table t1_tmp';
insert into t1_tmp (col1) select col1 from t1 where mod(col2, 2) = 0;
for c in (select col1 from t1_tmp)
loop
delete from t1 where t1.col1 = c.col1;
v$_compteur := v$_compteur +1;
if v$_compteur = 50000 then
-- commit;
v$_compteur := 0;
end if;
end loop;
dbms_output.put_line(' - Méthode TMP + PL/SQL : ' || to_char(dbms_utility.get_time() - v$_time));
rollback;
v$_time := dbms_utility.get_time();
delete from t1 where mod(col2, 2) = 0;
dbms_output.put_line(' - Méthode ensembliste : ' || to_char(dbms_utility.get_time() - v$_time));
rollback;
end;
/ |
Résultat :
Scénario 1%
- Méthode TMP + PL/SQL : 66
- Méthode ensembliste : 38
Scénario 15%
- Méthode TMP + PL/SQL : 561
- Méthode ensembliste : 256
Scénario 50%
- Méthode TMP + PL/SQL : 1889
- Méthode ensembliste : 777
Partager