Vấn đề
Thời gian phân tích cú pháp có thể tăng theo cấp số nhân với một số loại câu lệnh nhất định, đặc biệt là INSERT ALL
. Ví dụ:
--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;
Chạy tệp theo dõi thông qua tkprof và bạn có thể thấy thời gian Phân tích cú pháp tăng đáng kể đối với một số lượng lớn hàng. Ví dụ:
100 hàng:
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 hàng:
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
Giải pháp
- Chia câu lệnh lớn của bạn thành nhiều câu lệnh nhỏ hơn. Rất khó để tìm ra kích thước tối ưu. Trên một số phiên bản của Oracle, có một số hàng kỳ diệu sẽ gây ra sự cố. Tôi thường đi khoảng 100 hàng - đủ để nhận được hầu hết các lợi ích của việc nhóm các câu lệnh, nhưng đủ thấp để tránh lỗi phân tích cú pháp. HOẶC ...
- Thử
insert into ... select ... from dual union all ...
thay vào đó. Nó thường chạy nhanh hơn nhiều, mặc dù hiệu suất phân tích cú pháp của nó cũng có thể giảm đáng kể theo kích thước. - Nâng cấp Oracle. Hiệu suất phân tích cú pháp đã được cải thiện trong các phiên bản mới hơn. Tôi không thể tái tạo sự cố này trong phiên bản 12.2 nữa.
Cảnh báo
Đừng học bài học sai lầm từ điều này. Nếu bạn lo lắng về hiệu suất SQL, 99% thời gian bạn nên nhóm những thứ tương tự lại với nhau thay vì tách chúng ra. Bạn đang làm mọi thứ đúng cách, bạn vừa gặp phải một lỗi kỳ lạ. (Tôi đã tìm kiếm Bộ phận hỗ trợ Oracle của mình nhưng không thể tìm thấy lỗi chính thức cho vấn đề này.)