Problem
Czas parsowania może wzrosnąć wykładniczo w przypadku niektórych typów instrukcji, zwłaszcza INSERT ALL
. Na przykład:
--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;
Uruchom plik śledzenia przez tkprof, a zobaczysz, że czas analizy znacznie wzrasta dla dużej liczby wierszy. Na przykład:
100 wierszy:
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 wierszy:
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
Rozwiązania
- Podziel duże stwierdzenie na kilka mniejszych. Trudno znaleźć optymalny rozmiar. W niektórych wersjach Oracle istnieje magiczna liczba wierszy, które powodują problem. Zwykle wybieram około 100 wierszy — wystarczająco dużo, aby uzyskać większość korzyści z grupowania instrukcji, ale wystarczająco mało, aby uniknąć błędu parsowania. LUB...
- Wypróbuj
insert into ... select ... from dual union all ...
zamiast tego. Zwykle działa znacznie szybciej, chociaż wydajność analizowania może również znacznie pogorszyć się wraz z rozmiarem. - Uaktualnij Oracle. Wydajność analizowania poprawiła się w nowszych wersjach. Nie mogę już odtworzyć tego problemu w wersji 12.2.
Ostrzeżenie
Nie wyciągaj z tego złej lekcji. Jeśli martwisz się wydajnością SQL, w 99% przypadków lepiej będzie grupować podobne rzeczy, zamiast je rozdzielać. Robisz rzeczy we właściwy sposób, właśnie natknąłeś się na dziwny błąd. (Przeszukałem My Oracle Support, ale nie mogłem znaleźć oficjalnego błędu w tym zakresie.)