Buitenlandse gegevenswrapper
Doorgaans zijn joins of afgeleide tabellen van subquery's of CTE's niet beschikbaar op de externe server en moeten ze lokaal worden uitgevoerd. D.w.z. alle rijen die overblijven na de simpele WHERE
clausule in uw voorbeeld moet lokaal worden opgehaald en verwerkt, zoals u hebt opgemerkt.
Als al het andere faalt, kunt u de subquery uitvoeren SELECT id FROM lookup_table WHERE x = 5
en voeg de resultaten samen in de queryreeks.
Handiger is dat u dit kunt automatiseren met dynamische SQL en EXECUTE
in een PL/pgSQL-functie. Vind ik leuk:
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;
Gerelateerd:
- Tabelnaam als een PostgreSQL-functieparameter
Of probeer deze zoekopdracht op SO.
Of u kunt het meta-commando \gexec
. gebruiken in psql. Zie:
- Kolomnamen filteren uit bestaande tabel voor SQL DDL-instructie
Of dit zou kunnen werken: (Feedback zegt werkt niet .)
SELECT id,c1,c2,c3
FROM big_table
WHERE c1 = 2
AND id = ANY (ARRAY(SELECT id FROM lookup_table WHERE x = 5));
Als ik lokaal test, krijg ik een queryplan als volgt:
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)
Vetgedrukte nadruk van mij.
De parameter $0
in het plan wekt hoop. De gegenereerde array kan iets zijn dat Postgres kan doorgeven om op afstand te worden gebruikt. Ik zie geen soortgelijk plan met een van je andere pogingen of meer die ik zelf heb geprobeerd. Kun je testen met je fdw?
Gerelateerde vraag over postgres_fdw
:
- postgres_fdw:mogelijk om gegevens naar een buitenlandse server te pushen voor deelname?
Algemene techniek in SQL
Dat is een ander verhaal. Gebruik gewoon een CTE. Maar ik verwacht niet dat dat helpt bij de 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 veranderd (verbeterd) gedrag, zodat CTE's als subquery's inline kunnen worden geplaatst, mits enkele randvoorwaarden. Maar, de handleiding citerend:
U kunt die beslissing negeren door
MATERIALIZED
op te geven aparte berekening van de WITH-query forceren
Dus:
WITH cte AS MATERIALIZED (SELECT id FROM lookup_table WHERE x = 5)
...
Normaal gesproken zou dit niet nodig moeten zijn als uw DB-server correct is geconfigureerd en de kolomstatistieken up-to-date zijn. Maar er zijn hoekgevallen met ongelijke gegevensverdeling ...