sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur man tvingar utvärdering av subquery innan man går med / trycker ner till främmande server

Utländsk dataomslag

Vanligtvis är anslutningar eller andra härledda tabeller från underfrågor eller CTE:er inte tillgängliga på den främmande servern och måste exekveras lokalt. Dvs alla rader kvar efter den enkla WHERE klausulen i ditt exempel måste hämtas och bearbetas lokalt som du observerade.

Om allt annat misslyckas kan du köra underfrågan SELECT id FROM lookup_table WHERE x = 5 och sammanfoga resultaten i frågesträngen.

Mer bekvämt kan du automatisera detta med dynamisk SQL och EXECUTE i en PL/pgSQL-funktion. Gilla:

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;

Relaterat:

  • Tabellnamn som en PostgreSQL-funktionsparameter

Eller prova den här sökningen på SO.

Eller så kan du använda metakommandot \gexec i psql. Se:

  • Filtrera kolumnnamn från befintlig tabell för SQL DDL-sats

Eller det här kan fungera: (Feedback säger att fungerar inte .)

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

När jag testar lokalt får jag en frågeplan så här:

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)

Djärv betoning min.

Parametern $0 i planen inger hopp. Den genererade arrayen kan vara något som Postgres kan skicka vidare för att användas på distans. Jag ser inte en liknande plan med några av dina andra försök eller några fler som jag försökte själv. Kan du testa med din fdw?

Relaterad fråga om postgres_fdw :

  • postgres_fdw:möjligt att skicka data till främmande server för att ansluta?

Allmän teknik i SQL

Det är en annan historia. Använd bara en CTE. Men jag förväntar mig inte att 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 ändrat (förbättrat) beteende, så att CTE:er kan infogas som underfrågor, givet vissa förutsättningar. Men citerar manualen:

Du kan åsidosätta det beslutet genom att ange MATERIALIZED för att tvinga fram separat beräkning av WITH-frågan

Så:

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

Vanligtvis bör inget av detta vara nödvändigt om din DB-server är korrekt konfigurerad och kolumnstatistiken är uppdaterad. Men det finns hörnfall med ojämn datafördelning ...




  1. Hur delar jag upp utdata från mysqldump i mindre filer?

  2. mySQL konvertera varchar till datum

  3. Hur släpper man en kolumn i SQL?

  4. Sammanfoga flera rader i en array med SQL på PostgreSQL