PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Cách buộc đánh giá truy vấn con trước khi tham gia / đẩy xuống máy chủ nước ngoài

Trình bao bọc dữ liệu nước ngoài

Thông thường, các phép nối hoặc bất kỳ bảng dẫn xuất nào từ các truy vấn con hoặc CTE không có sẵn trên máy chủ nước ngoài và phải được thực thi cục bộ. Tức là tất cả các hàng còn lại sau WHERE đơn giản mệnh đề trong ví dụ của bạn phải được truy xuất và xử lý cục bộ như bạn đã quan sát.

Nếu vẫn thất bại, bạn có thể thực hiện truy vấn con SELECT id FROM lookup_table WHERE x = 5 và nối kết quả vào chuỗi truy vấn.

Thuận tiện hơn, bạn có thể tự động hóa việc này bằng SQL động và EXECUTE trong một hàm PL / pgSQL. Như:

CREATE OR REPLACE FUNCTION my_func(_c1 int, _l_id int)
   RETURNS TABLE(id int, c1 int, c2 int, c3 int) AS
$func$
BEGIN
   RETURN QUERY EXECUTE
     'SELECT id,c1,c2,c3 FROM big_table
      WHERE  c1 = $1
      AND    id = ANY ($2)'
   USING _c1
       , ARRAY(SELECT l.id FROM lookup_table l WHERE l.x = _l_id);
END
$func$  LANGUAGE plpgsql;

Có liên quan:

  • Tên bảng dưới dạng tham số hàm PostgreSQL

Hoặc thử tìm kiếm này trên SO.

Hoặc bạn có thể sử dụng meta-command \gexec trong psql. Xem:

  • Lọc tên cột từ bảng hiện có cho câu lệnh SQL DDL

Hoặc điều này có thể hoạt động: (Phản hồi cho biết không hoạt động .)

SELECT id,c1,c2,c3
FROM   big_table
WHERE  c1 = 2
AND    id = ANY (ARRAY(SELECT id FROM lookup_table WHERE x = 5));

Đang kiểm tra cục bộ, tôi nhận được một kế hoạch truy vấn như sau:

Index Scan using big_table_idx on big_table (cost= ...)
  Index Cond: (id = ANY ($0))
  Filter: (c1 = 2)
  InitPlan 1 (returns $0)
    ->  Seq Scan on lookup_table  (cost= ...)
          Filter: (x = 5)

Nhấn mạnh đậm của tôi.

Tham số $0 trong kế hoạch truyền cảm hứng cho hy vọng. Mảng được tạo có thể là thứ mà Postgres có thể chuyển để được sử dụng từ xa. Tôi không thấy một kế hoạch tương tự với bất kỳ nỗ lực nào khác của bạn hoặc một số kế hoạch khác mà tôi đã tự mình thử. Bạn có thể kiểm tra với fdw của bạn không?

Câu hỏi liên quan về postgres_fdw :

  • postgres_fdw:có thể đẩy dữ liệu sang máy chủ nước ngoài để tham gia không?

Kỹ thuật chung trong SQL

Đó là một câu chuyện khác. Chỉ cần sử dụng CTE. Nhưng tôi không hy vọng điều đó sẽ giúp ích cho FDW.

WITH cte AS (SELECT id FROM lookup_table WHERE x = 5)
SELECT id,c1,c2,c3
FROM   big_table b
JOIN   cte USING (id)
WHERE  b.c1 = 2;

PostgreSQL 12 đã thay đổi (cải thiện) hành vi, để CTE có thể được nội tuyến giống như các truy vấn con, với một số điều kiện tiên quyết. Nhưng, trích dẫn sách hướng dẫn:

Bạn có thể ghi đè quyết định đó bằng cách chỉ định MATERIALIZED để buộc tính toán riêng truy vấn WITH

Vì vậy:

WITH cte AS MATERIALIZED (SELECT id FROM lookup_table WHERE x = 5)
...

Thông thường, không cần thiết trong số này nếu máy chủ DB của bạn được định cấu hình đúng cách và thống kê cột được cập nhật. Nhưng có những trường hợp góc với sự phân bố dữ liệu không đồng đều ...




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sẽ tốt hơn nếu sử dụng nhiều cơ sở dữ liệu với một lược đồ, hay một cơ sở dữ liệu với nhiều lược đồ?

  2. Định dạng số với dấu phẩy trong PostgreSQL

  3. Các chuỗi không bị ảnh hưởng bởi các giao dịch?

  4. thứ tự cột trong câu lệnh SELECT * - được đảm bảo?

  5. Sự cố với createb trong postgres