Oracle
 sql >> Base de données >  >> RDS >> Oracle

Un moyen plus rapide d'insérer, via un script, dans Oracle ?

Problème

Le temps d'analyse peut augmenter de façon exponentielle avec certains types d'instructions, en particulier INSERT ALL . Par exemple :

--Clear any cached statements, so we can consistently reproduce the problem.
alter system flush shared_pool;
alter session set sql_trace = true;

--100 rows
INSERT ALL
    INTO FileIds(Id,FileTypeGroupId) VALUES(1, 1)
    ...
    repeat 100 times
    ...
select * from dual;

--500 rows
INSERT ALL
    INTO FileIds(Id,FileTypeGroupId) VALUES(1, 1)
    ...
    repeat 500 times
    ...
select * from dual;

alter session set sql_trace = false;

Exécutez le fichier de trace via tkprof et vous pouvez voir que le temps d'analyse augmente considérablement pour un grand nombre de lignes. Par exemple :

100 lignes :

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.06       0.05          0          1          0           0
Execute      1      0.00       0.00          0        100        303         100
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.06       0.05          0        101        303         100

500 lignes :

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1     14.72      14.55          0          0          0           0
Execute      1      0.01       0.02          0        502       1518         500
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2     14.74      14.58          0        502       1518         500

Solutions

  1. Divisez votre déclaration volumineuse en plusieurs déclarations plus petites. Difficile de trouver la taille optimale. Sur certaines versions d'Oracle, il existe un nombre magique de lignes qui causeront le problème. J'utilise généralement environ 100 lignes - assez pour tirer le meilleur parti des instructions de regroupement, mais suffisamment bas pour éviter le bogue d'analyse. OU...
  2. Essayez l'insert into ... select ... from dual union all ... méthode à la place. Il s'exécute généralement beaucoup plus rapidement, bien que ses performances d'analyse puissent également se dégrader considérablement avec la taille.
  3. Mettre à niveau Oracle. Les performances d'analyse se sont améliorées dans les versions plus récentes. Je ne peux plus reproduire ce problème dans la version 12.2.

Avertissement

N'en tirez pas la mauvaise leçon. Si vous vous inquiétez des performances SQL, 99 % du temps, vous feriez mieux de regrouper des éléments similaires au lieu de les séparer. Vous faites les choses de la bonne manière, vous venez de rencontrer un bug étrange. (J'ai cherché dans My Oracle Support mais je n'ai pas trouvé de bogue officiel pour cela.)