Vì vậy, câu hỏi của bạn cuối cùng đã rút gọn thành "how java.sql.PreparedStatement
chơi với PostgreSQL ". Cuối cùng, hãy xem câu trả lời về" điều này hoạt động như thế nào với các kế hoạch do máy chủ chuẩn bị ".
Đây là câu trả lời:điều đó phụ thuộc vào trình điều khiển JDBC mà bạn sử dụng.
TL; DR :trong trình điều khiển hiện đại, câu lệnh do máy chủ chuẩn bị sẽ tồn tại cho đến khi kết nối ngừng hoạt động hoặc cho đến khi câu lệnh bị loại bỏ bởi một câu lệnh khác (loại bỏ LRU thông thường).
Lưu ý:Máy chủ PostgreSQL không thể chia sẻ câu lệnh đã chuẩn bị qua các kết nối cơ sở dữ liệu, do đó trình điều khiển JDBC tốt nhất có thể làm là giữ kế hoạch được lưu trong bộ nhớ cache trong mỗi kết nối.
Lưu ý:JDBC spec yêu cầu sử dụng ?, ?
cho trình giữ chỗ ràng buộc, trong khi máy chủ muốn $1, $2
do đó, trình điều khiển JDBC cũng lưu vào bộ nhớ cache cái gọi là văn bản SQL được phân tích cú pháp.
Có hai trình điều khiển JDBC nổi tiếng:pgjdbc và pgjdbc-ng
pgjdbc
https://github.com/pgjdbc/pgjdbc
Vì pgjdbc 9.4-1202
nó tự động lưu trữ các kế hoạch phía máy chủ khi sử dụng PreparedStatement
.Lưu ý:các câu lệnh được lưu vào bộ nhớ đệm ngay cả khi bạn close()
PreparedStatement
.Để đến chuẩn bị phía máy chủ, bạn cần thực hiện truy vấn 5 lần (có thể được định cấu hình qua prepareThreshold
).
Hiện tại, bộ nhớ cache được triển khai trên mỗi kết nối. Theo mặc định pgjdbc lưu vào bộ nhớ đệm 256 (preparedStatementCacheQueries
) truy vấn và tối đa preparedStatementCacheSizeMiB
trong số các truy vấn. Đây là một cài đặt thận trọng, vì vậy bạn có thể muốn điều chỉnh nó. Xem tài liệu
để mô tả các thuộc tính. bộ nhớ đệm bao gồm cả các câu lệnh được phân tích cú pháp và do máy chủ chuẩn bị.
Sự cố github: https://github.com/pgjdbc/pgjdbc/pull/319
pgjdbc-ng
https://github.com/impossibl/pgjdbc-ng
Tôi không thích pgjdbc-ng, tuy nhiên có vẻ như nó thực hiện cả phân tích cú pháp (kích thước bộ nhớ đệm mặc định là 250 truy vấn) và chuẩn bị máy chủ (kích thước bộ nhớ đệm mặc định là 50 truy vấn). Việc hỗ trợ các câu lệnh được chuẩn bị từ phía máy chủ đã hạ cánh vào ngày 24 tháng 2 năm 2014, vì vậy nếu bạn sử dụng phiên bản gần đây nhất, bạn có thể nhận được bộ nhớ đệm câu lệnh.
Lưu ý:nếu bạn vô tình sử dụng các truy vấn rất dài, bạn có thể nhấn OutOfMemory
vì pgjdbc-ng không thể loại bỏ các mục nhập dựa trên số byte được giữ lại.
Bộ nhớ đệm là bộ nhớ cache cho mỗi kết nối, do đó nó được sử dụng một cách rõ ràng ngay cả khi bạn đóng các câu lệnh.
Tôi không thể nói nhiều về hiệu suất pgjdbc-ng mặc dù lần trước tôi đã cố gắng ném jmh vào nó, nó không thành công với các ngoại lệ ngẫu nhiên.
Vấn đề github: https://github.com/impossibl/pgjdbc-ng/pull/ 69
Kế hoạch do máy chủ chuẩn bị
PostgreSQL có PREPARE
và DEALLOCATE
các lệnh để tham chiếu câu lệnh khi gửi EXEC
qua dây. Nó tối ưu hóa hai điều:
- Khi sử dụng
PREPARE
câu lệnh d (nói cách khác là câu lệnh do máy chủ chuẩn bị), máy khách không phải gửi đi gửi lại văn bản truy vấn. Nó chỉ gửi một tên truy vấn ngắn và các giá trị cho các biến liên kết. - Kể từ 9.2, cơ sở dữ liệu vẫn cố gắng lập kế hoạch lại một số lần thực thi đầu tiên của một truy vấn. Nó làm như vậy để thử nếu truy vấn cần nhiều kế hoạch hoặc nếu kế hoạch chung là đủ tốt. Cuối cùng (ngay lập tức nếu truy vấn không có tham số), cơ sở dữ liệu có thể chuyển sang kế hoạch chung .
- Kể từ ngày 12, có một cài đặt để buộc TẤT CẢ các câu lệnh do máy chủ chuẩn bị phải được thực thi với các kế hoạch chung hoặc tùy chỉnh:plan_cache_mode
=
auto | force_custom_plan | force_generic_plan
Nói cách khác, PreparedStatement
tối ưu hóa cả phân tích cú pháp truy vấn ở phía JDBC và lập kế hoạch truy vấn ở phía cơ sở dữ liệu.
Thông tin thêm tại đây: http://blog.endpoint .com / 2014/04 / custom-plan-ready-statement-in.html
Các câu lệnh được soạn sẵn trong PL / pgSQL
Theo tài liệu, PostgreSQL caches kế hoạch cho các truy vấn được sử dụng trong PL / pgSQL. Điều này xảy ra sau một vài lần thực thi (3 hoặc 5, tôi không nhớ chính xác ngưỡng), vì vậy sau khi bạn tạo thủ tục được lưu trữ, nó có thể hơi chậm một chút, tuy nhiên sau đó nó sẽ chuyển sang các kế hoạch được lưu trong bộ nhớ cache (miễn là cơ sở dữ liệu đồng ý sử dụng kế hoạch chung cho một truy vấn cụ thể).
Nói cách khác, để đạt được "kế hoạch thực thi được lưu trong bộ nhớ cache", bạn cần sử dụng trình điều khiển JDBC cập nhật hoặc bạn có thể gói tất cả các truy vấn của mình vào các thủ tục được lưu trữ. thường ngắn hơn nhiều so với các truy vấn soạn thủ tục.