Проблем
Времето за синтактичен анализ може да се увеличи експоненциално с определени типове изрази, особено INSERT ALL
. Например:
--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;
Пуснете файла за проследяване през tkprof и можете да видите, че времето за анализ се увеличава драстично за голям брой редове. Например:
100 реда:
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 реда:
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
Решения
- Разделете голямото си изявление на няколко по-малки изявления. Трудно е да се намери оптималният размер. В някои версии на Oracle има магически брой редове, които ще причинят проблема. Обикновено използвам около 100 реда - достатъчно, за да получа повечето от предимствата на групиращите изрази, но достатъчно ниско, за да избегна грешката при анализа. ИЛИ...
- Опитайте
insert into ... select ... from dual union all ...
вместо това метод. Обикновено работи много по-бързо, въпреки че производителността на анализа може също да се влоши значително с размера. - Надстройте Oracle. Производителността на синтактичния анализ се подобри в по-новите версии. Вече не мога да възпроизвеждам този проблем във версия 12.2.
Предупреждение
Не извличайте грешен урок от това. Ако се притеснявате за производителността на SQL, в 99% от времето е по-добре да групирате подобни неща заедно, вместо да ги разделяте. Правите нещата по правилния начин, просто се натъкнахте на странен бъг. (Потърсих моята поддръжка на Oracle, но не можах да намеря официална грешка за това.)