Pembungkus data asing
Biasanya, gabungan atau tabel turunan apa pun dari subkueri atau CTE tidak tersedia di server asing dan harus dijalankan secara lokal. Yaitu, semua baris yang tersisa setelah WHERE
simple sederhana klausa dalam contoh Anda harus diambil dan diproses secara lokal seperti yang Anda amati.
Jika semuanya gagal, Anda dapat menjalankan subquery SELECT id FROM lookup_table WHERE x = 5
dan menggabungkan hasil ke dalam string kueri.
Lebih mudahnya, Anda dapat mengotomatiskan ini dengan SQL dinamis dan EXECUTE
dalam fungsi PL/pgSQL. Seperti:
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;
Terkait:
- Nama tabel sebagai parameter fungsi PostgreSQL
Atau coba pencarian ini di SO.
Atau Anda dapat menggunakan meta-command \gexec
di psql. Lihat:
- Filter nama kolom dari tabel yang ada untuk pernyataan SQL DDL
Atau ini mungkin berhasil: (Umpan balik mengatakan tidak berfungsi .)
SELECT id,c1,c2,c3
FROM big_table
WHERE c1 = 2
AND id = ANY (ARRAY(SELECT id FROM lookup_table WHERE x = 5));
Menguji secara lokal, saya mendapatkan paket kueri seperti ini:
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)
Penekanan saya yang berani.
Parameter $0
dalam rencana mengilhami harapan. Array yang dihasilkan mungkin sesuatu yang dapat diteruskan Postgres untuk digunakan dari jarak jauh. Saya tidak melihat rencana serupa dengan upaya Anda yang lain atau lebih saya mencoba sendiri. Bisakah Anda menguji dengan fdw Anda?
Pertanyaan terkait tentang postgres_fdw
:
- postgres_fdw:apakah mungkin untuk mendorong data ke server asing untuk bergabung?
Teknik umum dalam SQL
Itu cerita yang berbeda. Cukup gunakan CTE. Tapi saya tidak berharap itu membantu PLRT Asing.
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 perilaku yang diubah (ditingkatkan), sehingga CTE dapat digarisbawahi seperti subkueri, dengan beberapa prasyarat. Tapi, mengutip manual:
Anda dapat mengganti keputusan itu dengan menentukan
MATERIALIZED
untuk memaksa perhitungan terpisah dari kueri WITH
Jadi:
WITH cte AS MATERIALIZED (SELECT id FROM lookup_table WHERE x = 5)
...
Biasanya, semua ini tidak diperlukan jika server DB Anda dikonfigurasi dengan benar dan statistik kolom diperbarui. Tetapi ada kasus sudut dengan distribusi data yang tidak merata ...