sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvordan man tvinger evaluering af underforespørgsel, før man tilslutter sig/skubber ned til en fremmed server

Udenlandsk dataindpakning

Typisk er joins eller eventuelle afledte tabeller fra underforespørgsler eller CTE'er ikke tilgængelige på den udenlandske server og skal udføres lokalt. Dvs. alle rækker tilbage efter den simple WHERE klausulen i dit eksempel skal hentes og behandles lokalt, som du har observeret.

Hvis alt andet fejler, kan du udføre underforespørgslen SELECT id FROM lookup_table WHERE x = 5 og sammenkæde resultater i forespørgselsstrengen.

Mere bekvemt kan du automatisere dette med dynamisk SQL og EXECUTE i en PL/pgSQL-funktion. Ligesom:

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;

Relateret:

  • Tabelnavn som en PostgreSQL-funktionsparameter

Eller prøv denne søgning på SO.

Eller du kan bruge metakommandoen \gexec i psql. Se:

  • Filtrer kolonnenavne fra eksisterende tabel for SQL DDL-sætning

Eller dette kan virke: (Feedback siger virker ikke .)

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

Ved at teste lokalt får jeg en forespørgselsplan som denne:

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)

Fed fremhævelse mine.

Parameteren $0 i planen giver håb. Det genererede array kan være noget Postgres kan videregive til at blive brugt eksternt. Jeg kan ikke se en lignende plan med nogen af ​​dine andre forsøg eller nogle flere, jeg prøvede selv. Kan du teste med din fdw?

Relateret spørgsmål vedrørende postgres_fdw :

  • postgres_fdw:muligt at skubbe data til en fremmed server for joinforbindelse?

Generel teknik i SQL

Det er en anden historie. Bare brug en CTE. Men jeg forventer ikke, at det hjælper med 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 ændret (forbedret) adfærd, så CTE'er kan indlejres som underforespørgsler, givet nogle forudsætninger. Men med henvisning til manualen:

Du kan tilsidesætte denne beslutning ved at angive MATERIALIZED for at fremtvinge separat beregning af WITH-forespørgslen

Så:

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

Typisk skulle intet af dette være nødvendigt, hvis din DB-server er konfigureret korrekt, og kolonnestatistikken er opdateret. Men der er hjørnesager med ujævn datafordeling ...




  1. java.security.AccessControlException:adgang nægtet (java.security.SecurityPermission authProvider.SunMSCAPI)

  2. SQL opdatering top1 række forespørgsel

  3. Indsæt resultater af en lagret procedure i en midlertidig tabel

  4. SQL SERVER – Trick – Kørsel af SSMS med forskellige Windows-kontoer