Problem
Analystiden kan öka exponentiellt med vissa typer av satser, särskilt INSERT ALL
. Till exempel:
--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;
Kör spårningsfilen genom tkprof, och du kan se Parse-tiden ökar dramatiskt för ett stort antal rader. Till exempel:
100 rader:
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 rader:
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
Lösningar
- Dela upp ditt stora påstående i flera mindre påståenden. Det är svårt att hitta den optimala storleken. På vissa versioner av Oracle finns det ett magiskt antal rader som kommer att orsaka problemet. Jag brukar gå på cirka 100 rader - tillräckligt för att få de flesta fördelarna med att gruppera påståenden, men tillräckligt lågt för att undvika analysfelet. ELLER...
- Prova
insert into ... select ... from dual union all ...
metod istället. Det går vanligtvis mycket snabbare, även om dess analysprestanda också kan försämras avsevärt med storleken. - Uppgradera Oracle. Analysprestandan har förbättrats i nyare versioner. Jag kan inte längre återskapa det här problemet i version 12.2.
Varning
Lär dig inte fel läxa av detta. Om du är orolig för SQL-prestanda är det 99 % av gångerna bättre att gruppera liknande saker istället för att dela isär dem. Du gör saker på rätt sätt, du har bara stött på en konstig bugg. (Jag sökte i My Oracle Support men kunde inte hitta en officiell bugg för detta.)