sql >> Database >  >> RDS >> PostgreSQL

Hoe evaluatie van subquery te forceren voordat u zich aansluit bij / naar een buitenlandse server duwt?

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 ...




  1. Functie voor datumnotatie in SQL Server

  2. Herhaal een string meerdere keren in MySQL - REPEAT()

  3. MySQL TABLE-instructie

  4. 10 handige tips voor het afstemmen van MySQL-prestaties