Điều sai với con trỏ là chúng thường bị lạm dụng, cả trong Oracle
và trong MS SQL
.
Con trỏ để giữ một tập hợp kết quả ổn định mà bạn có thể truy xuất từng hàng một. Chúng được tạo ngầm khi truy vấn của bạn được chạy và được đóng lại khi kết thúc.
Tất nhiên để giữ một tập kết quả như vậy cần một số tài nguyên:locks
, latches
, memory
, thậm chí disk space
.
Các tài nguyên này được giải phóng càng nhanh thì càng tốt.
Giữ con trỏ mở cũng giống như mở cửa tủ lạnh
Bạn không làm điều đó hàng giờ mà không cần thiết, nhưng không có nghĩa là bạn không bao giờ được mở tủ lạnh.
Điều đó có nghĩa là:
- Bạn không nhận được kết quả của mình theo từng hàng và tính tổng chúng:bạn gọi
SQL
củaSUM
thay vào đó. - Bạn không thực hiện toàn bộ truy vấn và nhận được kết quả đầu tiên từ con trỏ:bạn thêm
rownum <= 10
điều kiện cho truy vấn của bạn
, v.v.
Đối với Oracle
, việc xử lý các con trỏ của bạn bên trong một thủ tục yêu cầu SQL/PLSQL context switch
khét tiếng điều này xảy ra mỗi khi bạn nhận được kết quả của một SQL
truy vấn ra khỏi con trỏ.
Nó liên quan đến việc chuyển một lượng lớn dữ liệu giữa các luồng và đồng bộ hóa các luồng.
Đây là một trong những điều khó chịu nhất trong Oracle
.
Một trong những hậu quả ít rõ ràng hơn của hành vi đó là cần tránh các trình kích hoạt trong Oracle nếu có thể.
Tạo trình kích hoạt và gọi DML
chức năng tương đương với việc mở con trỏ để chọn các hàng được cập nhật và gọi mã kích hoạt cho mỗi hàng của con trỏ này.
Sự tồn tại của trình kích hoạt (ngay cả trình kích hoạt trống) có thể làm chậm DML
hoạt động 10 times
trở lên.
Tập lệnh thử nghiệm vào 10g
:
SQL> CREATE TABLE trigger_test (id INT NOT NULL)
2 /
Table created
Executed in 0,031 seconds
SQL> INSERT
2 INTO trigger_test
3 SELECT level
4 FROM dual
5 CONNECT BY
6 level <= 1000000
7 /
1000000 rows inserted
Executed in 1,469 seconds
SQL> COMMIT
2 /
Commit complete
Executed in 0 seconds
SQL> TRUNCATE TABLE trigger_test
2 /
Table truncated
Executed in 3 seconds
SQL> CREATE TRIGGER trg_test_ai
2 AFTER INSERT
3 ON trigger_test
4 FOR EACH ROW
5 BEGIN
6 NULL;
7 END;
8 /
Trigger created
Executed in 0,094 seconds
SQL> INSERT
2 INTO trigger_test
3 SELECT level
4 FROM dual
5 CONNECT BY
6 level <= 1000000
7 /
1000000 rows inserted
Executed in 17,578 seconds
1.47
giây mà không có trình kích hoạt, 17.57
giây với một trình kích hoạt trống không làm gì cả.