Tôi không thể nói về giao diện Perl phía máy khách nhưng tôi có thể làm sáng tỏ một số thứ ở phía máy chủ PostgreSQL.
PostgreSQL đã có các câu lệnh chuẩn bị và phát biểu chưa chuẩn bị. Các câu lệnh không chuẩn bị được phân tích cú pháp, lập kế hoạch và thực hiện ngay lập tức. Họ cũng làm không thay thế thông số hỗ trợ. Trên một đồng bằng psql
vỏ bạn có thể hiển thị kế hoạch truy vấn của họ như thế này:
tmpdb> explain select * from sometable where flag = true;
Mặt khác có những chuẩn bị phát biểu: Họ thường (xem "ngoại lệ" dưới đây) phân tích và lên kế hoạch trong một bước và thực hiện trong một bước thứ hai. Chúng có thể được thực hiện lại nhiều lần với các thông số khác nhau, vì chúng làm thay thế thông số hỗ trợ.Tương đương trong psql
là thế này:
tmpdb> prepare foo as select * from sometable where flag = $1;
tmpdb> explain execute foo(true);
Bạn có thể thấy, đó là kế hoạch là khác biệt so với kế hoạch trong báo cáo không chuẩn bị, bởi vì kế hoạch đã diễn ra đã có trong giai đoạn prepare
như mô tả trong doc cho PREPARE:
Khi lệnh PREPARE được thực thi, báo cáo kết quả cụ thể là phân tích cú pháp , viết lại, và lên kế hoạch. Khi một lệnh EXECUTE là sau đó được ban hành, câu lệnh đã chuẩn bị chỉ cần được thực hiện. Do đó, các giai đoạn phân tích cú pháp, viết lại và lập kế hoạch chỉ được thực hiện một lần, thay vì mỗi khi câu lệnh được thực thi.
này cũng có nghĩa, rằng kế hoạch là KHÔNG tối ưu hóa cho các thông số thay: Trong ví dụ đầu tiên có thể sử dụng một chỉ số cho flag
vì PostgreSQL biết rằng trong vòng một triệu mục chỉ có mười có giá trị true
. Lý do này là không thể khi PostgreSQL sử dụng một câu lệnh chuẩn bị. Trong trường hợp đó, một kế hoạch được tạo ra sẽ làm việc cho tất cả các giá trị tham số có thể tốt nhất có thể. Điều này có thể loại trừ chỉ mục được đề cập vì tìm nạp phần tốt hơn của bảng hoàn chỉnh qua truy cập ngẫu nhiên (do chỉ mục) chậm hơn so với quét tuần tự đơn giản. Tài liệu PREPARE xác nhận điều này:
Trong một số trường hợp, kế hoạch truy vấn được tạo ra cho câu lệnh chuẩn bị sẽ kém hơn so với kế hoạch truy vấn đã được chọn nếu tuyên bố đã được gửi và thực hiện bình thường. Điều này là do khi tuyên bố được lên kế hoạch và kế hoạch cố gắng xác định kế hoạch truy vấn tối ưu, các giá trị thực tế của bất kỳ tham số nào được chỉ định trong câu lệnh không có sẵn. PostgreSQL thu thập số liệu thống kê về phân phối dữ liệu trong bảng và có thể sử dụng các giá trị không đổi trong một câu lệnh để đoán về kết quả có khả năng thực hiện câu lệnh. Vì dữ liệu này không có sẵn khi lập kế hoạch các câu lệnh chuẩn bị với các tham số, kế hoạch đã chọn có thể là tối ưu.
BTW - Về kế hoạch bộ nhớ đệm PREPARE doc cũng có một cái gì đó để nói:
báo cáo chuẩn bị chỉ kéo dài trong suốt thời gian của phiên cơ sở dữ liệu hiện hành. Khi phiên kết thúc, câu lệnh đã chuẩn bị bị lãng quên, vì vậy nó phải được tạo lại trước khi được sử dụng lại.
Cũng không có bộ nhớ đệm gói tự động và không lưu vào bộ nhớ đệm/tái sử dụng qua nhiều kết nối.
NGOẠI TRỪ: Tôi đã đề cập "thường". Các ví dụ psql
được hiển thị không phải là thứ mà một bộ điều hợp khách hàng như Perl DBI thực sự sử dụng. Nó sử dụng một số protocol nhất định. Ở đây thuật ngữ "truy vấn đơn giản" tương ứng với "truy vấn không chuẩn bị" trong psql
, cụm từ "extended query" tương ứng với "truy vấn đã chuẩn bị" với một ngoại lệ: Có sự phân biệt giữa (một) "tuyên bố chưa đặt tên" và (có thể nhiều) " báo cáo có tên ". Về các tuyên bố có tên là doc nói:
Các câu lệnh được chuẩn bị có tên cũng có thể được tạo và truy cập ở cấp lệnh SQL, sử dụng PREPARE và EXECUTE.
và cũng: lập kế hoạch
Query cho tên đối tượng chuẩn bị-tuyên bố xảy ra khi nhắn Parse được xử lý.
Vì vậy, trong trường hợp này, việc lập kế hoạch được thực hiện mà không có tham số như được mô tả ở trên cho PREPARE
- không có gì mới.
Ngoại lệ được đề cập là "tuyên bố chưa đặt tên". Tài liệu cho biết:
Tuyên bố được chuẩn bị chưa được đặt tên cũng được lên kế hoạch trong khi xử lý Parse nếu thông báo Parse xác định không có tham số. Nhưng nếu có các tham số, lập kế hoạch truy vấn xảy ra mỗi khi các tham số Bind được cung cấp. Điều này cho phép người lập kế hoạch sử dụng các giá trị thực tế của các tham số được cung cấp bởi mỗi thông điệp Bind, thay vì sử dụng các ước tính chung chung.
Và đây là lợi ích: Mặc dù câu lệnh chưa được đặt tên là "đã chuẩn bị" (nghĩa là có thể thay thế tham số), nó cũng có thể điều chỉnh kế hoạch truy vấn.
BTW: Việc xử lý chính xác câu lệnh chưa đặt tên đã thay đổi nhiều lần trong các phiên bản trước của máy chủ PostgreSQL. Bạn có thể tra cứu các tài liệu cũ để biết chi tiết nếu bạn thực sự muốn.
Lý - Perl/bất kỳ khách hàng:
Làm thế nào một client như Perl sử dụng giao thức là một câu hỏi hoàn toàn khác nhau. Một số khách hàng như trình điều khiển JDBC cho Java về cơ bản nói: Ngay cả khi lập trình viên sử dụng một câu lệnh đã chuẩn bị, thì năm thực thi đầu tiên (hoặc hơn) được ánh xạ nội bộ tới một "truy vấn đơn giản" (tức là không chuẩn bị hiệu quả), sau đó trình điều khiển chuyển sang " câu lệnh có tên ".
Vì vậy, một khách hàng có những lựa chọn này:
- Force (lại) lên kế hoạch cho từng thời gian bằng cách sử dụng "truy vấn đơn giản" giao thức.
- Lập kế hoạch một lần, thực hiện nhiều lần bằng giao thức "truy vấn mở rộng" và "tuyên bố tên" (kế hoạch có thể xấu vì lập kế hoạch được thực hiện mà không có tham số).
- Parse một lần, kế hoạch cho từng thực hiện (với phiên bản PostgreSQL hiện hành) bằng cách sử dụng các "truy vấn mở rộng" giao thức và "tuyên bố vô danh" và tuân theo một số điều hơn (cung cấp một số params trong "phân tích" tin nhắn)
- Chơi các thủ thuật hoàn toàn khác nhau như trình điều khiển JDBC.
Hiện tại Perl là gì: Tôi không biết. Nhưng đề cập đến "cá trích đỏ" không phải là rất khó xảy ra.
Câu hỏi hay! Điều này rất cụ thể về DBMS; DBMS khác nhau đưa ra các câu trả lời khác nhau (hơi). Kết quả thực có thể khác nhau đáng kể. Informix hỗ trợ một 'OPEN cursor USING ... WITH REOPTIMIZATION' mà không phải reparse SQL (tiết kiệm thời gian) nhưng làm lại kế hoạch truy vấn cho tập các tham số hiện tại. Điều đó lại khác với hầu hết các DBMS. –
Có. Câu hỏi này được chứng minh là gây tranh cãi đáng ngạc nhiên.Chúng tôi có upvotes và một downvote về câu hỏi và một trong những câu trả lời. – zgpmax
@hochgurgler: Nghi ngờ của bạn về loại không phù hợp là do chính nó là một mối quan tâm hợp lệ, PostgreSQL _has_ một số vấn đề đã biết ở đây. Nhưng xem xét phần đầu tiên của câu hỏi tôi nghĩ rằng hai vấn đề này không nên được trộn lẫn và phần thứ hai sẽ được xử lý tốt hơn bằng một câu hỏi riêng biệt. Bạn vui lòng chia nó? –