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
- 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...
- 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. - 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.)