Có thể có nhiều loại lô khác nhau liên quan và tôi sẽ đề cập đến phần trình điều khiển PostgreSQL JDBC (pgjdbc) của nó.
TL; DR:pgjdbc sử dụng ít vòng lặp mạng hơn trong trường hợp API hàng loạt được sử dụng. BatchedQuery
chỉ được sử dụng nếu reWriteBatchedInserts=true
được chuyển đến cài đặt kết nối pgjdbc.
Bạn có thể thấy https://www.slideshare.net/VladimirSitnikv/postgresql-and-jdbc-striving-for-high-performance có liên quan (slide 44, ...)
Khi nói đến thực thi truy vấn, độ trễ mạng thường chiếm một phần đáng kể trong thời gian đã trôi qua.
Giả sử trường hợp là chèn 10 hàng.
-
Không có lô (ví dụ:chỉ
PreparedStatement#execute
trong một vòng lặp). Người lái xe sẽ thực hiện những điều sauexecute query sync <-- wait for the response from the DB execute query sync <-- wait for the response from the DB execute query sync <-- wait for the response from the DB ...
Thời gian đáng chú ý sẽ được dành cho "chờ đợi DB"
-
API lô JDBC. Đó là
PreparedStatement#addBatch()
cho phép trình điều khiển gửi nhiều "thực thi truy vấn" trong một vòng mạng duy nhất. Tuy nhiên, việc triển khai hiện tại vẫn sẽ chia các lô lớn thành các lô nhỏ hơn để tránh bế tắc TCP.Các hành động sẽ tốt hơn nhiều:
execute query ... execute query execute query execute query sync <-- wait for the response from the DB
-
Lưu ý rằng ngay cả với
#addBatch
, có chi phí của lệnh "thực thi truy vấn". Máy chủ cần thời gian đáng kể để xử lý từng thư riêng lẻ.Một trong những cách để giảm số lượng truy vấn là sử dụng chèn nhiều giá trị. Ví dụ:
insert into tab(a,b,c) values (?,?,?), (?,?,?), ..., (?,?,?)
PostgreSQL này cho phép chèn nhiều hàng cùng một lúc. Hạn chế là bạn không có thông báo lỗi chi tiết (mỗi hàng). Hiện tại Hibernate không triển khai chèn nhiều giá trị.
Tuy nhiên, pgjdbc có thể ghi nhanh các chèn hàng loạt thông thường thành nhiều giá trị kể từ ngày 9.4.1209 (2016-07-15).
Để kích hoạt tính năng ghi lại nhiều giá trị, bạn cần thêm
reWriteBatchedInserts=true
thuộc tính kết nối. Tính năng này ban đầu được phát triển trong https://github.com/pgjdbc/pgjdbc/pull/491Nó đủ thông minh để sử dụng 2 câu lệnh để chèn 10 hàng. Câu lệnh đầu tiên là câu lệnh có giá trị 8 và câu lệnh thứ hai là câu lệnh có giá trị 2. Việc sử dụng quyền hạn của hai cho phép pgjdbc giữ cho số lượng các câu lệnh riêng biệt phù hợp và cải thiện hiệu suất vì các câu lệnh thường được sử dụng là do máy chủ chuẩn bị (xem Tuổi thọ của câu lệnh được chuẩn bị từ phía máy chủ PostgreSQL là gì)
BatchedQuery
đang đại diện cho loại câu lệnh nhiều giá trị đó, vì vậy bạn sẽ thấy lớp đó được sử dụng trongreWriteBatchedInserts=true
chỉ trường hợp.Hạn chế của tính năng này có thể bao gồm:chi tiết thấp hơn là "kết quả hàng loạt". Ví dụ:lô thông thường cung cấp cho bạn "số hàng mỗi câu lệnh", tuy nhiên trong trường hợp nhiều giá trị, bạn chỉ nhận được trạng thái "câu lệnh đã hoàn thành". Trên hết, trình viết lại nhanh có thể không phân tích cú pháp các câu lệnh SQL nhất định (ví dụ:https://github.com/pgjdbc/pgjdbc/issues/1045).