le prestazioni postgres_fdw sono lente


12

La seguente query su uno straniero richiede circa 5 secondi per essere eseguita su 3,2 milioni di righe:

SELECT x."IncidentTypeCode", COUNT(x."IncidentTypeCode") 
FROM "IntterraNearRealTimeUnitReflexes300sForeign" x 
WHERE x."IncidentDateTime" >= '05/01/2016' 
GROUP BY x."IncidentTypeCode" 
ORDER BY 1;

Quando eseguo la stessa query sulla tabella normale, ritorna in .6 secondi. I piani di esecuzione sono abbastanza diversi:

Tavolo normale

Sort  (cost=226861.20..226861.21 rows=4 width=4) (actual time=646.447..646.448 rows=7 loops=1) 
  Sort Key: "IncidentTypeCode" 
  Sort Method: quicksort  Memory: 25kB 
  -> HashAggregate (cost=226861.12..226861.16 rows=4 width=4) (actual  time=646.433..646.434 rows=7 loops=1)
     Group Key: "IncidentTypeCode"
     -> Bitmap Heap Scan on "IntterraNearRealTimeUnitReflexes300s" x  (cost=10597.63..223318.41 rows=708542 width=4) (actual time=74.593..342.110 rows=709376 loops=1) 
        Recheck Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone) 
        Rows Removed by Index Recheck: 12259 
        Heap Blocks: exact=27052 lossy=26888
        -> Bitmap Index Scan on idx_incident_date_time_300  (cost=0.00..10420.49 rows=708542 width=0) (actual time=69.722..69.722 rows=709376 loops=1) 
           Index Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone) 

Planning time: 0.165 ms 
Execution time: 646.512 ms

Tavolo straniero

Sort  (cost=241132.04..241132.05 rows=4 width=4) (actual time=4782.110..4782.112 rows=7 loops=1)   
  Sort Key: "IncidentTypeCode" 
  Sort Method: quicksort  Memory: 25kB
  -> HashAggregate  (cost=241131.96..241132.00 rows=4 width=4) (actual time=4782.097..4782.100 rows=7 loops=1)
     Group Key: "IncidentTypeCode"
     -> Foreign Scan on "IntterraNearRealTimeUnitReflexes300sForeign" x  (cost=10697.63..237589.25 rows=708542 width=4) (actual time=1.916..4476.946 rows=709376 loops=1) 

Planning time: 1.413 ms 
Execution time: 4782.660 ms

Penso di pagare un prezzo elevato per la GROUP BYclausola, che non viene passata al server straniero quando EXPLAIN VERBOSE:

SELECT
    "IncidentTypeCode"
FROM
    PUBLIC ."IntterraNearRealTimeUnitReflexes300s"
WHERE
    (
        (
            "IncidentDateTime" >= '2016-05-01 00:00:00' :: TIMESTAMP WITHOUT TIME ZONE
        )
    )

Questo restituisce 700k righe. C'è un modo per aggirare questo?

Ieri ho trascorso molto tempo a leggere questa pagina di documentazione e ho pensato di aver trovato la mia risposta con l'impostazione use_remote_estimatesu true, ma non ha avuto alcun effetto.

Ho accesso al server esterno per creare oggetti se necessario. Il valore data / ora nella WHEREclausola può essere qualsiasi; non proviene da un elenco di valori predefiniti.


3
Ci sono alcuni miglioramenti al pushdown in 9.6 che potrebbero essere di interesse: wiki.postgresql.org/wiki/NewIn96#postgres_fdw
Jack dice che prova topanswers.xyz il

Quando dici tabella normale vs tabella straniera stai correndo sulla stessa tabella (localmente e in remoto) o in realtà tabelle diverse (si legge come se fossero), se sono diverse controlla l'indicizzazione sul server remoto assicurati che siano le stesse siccome sembra che tu stia leggendo fonti di informazione completamente diverse IntterraNearRealTimeUnitReflexes300sForeignvs IntterraNearRealTimeUnitReflexes300se idx_incident_date_time_300 presumo che quelli del 300 siano gli stessi, ma potrebbe valere la pena verificare se l' idx_incident_date_time_300indice esiste sul server straniero
Ste Bov,

2
Da quanto ho capito, gli aggregati (COUNT) non vengono inviati al server remoto, il che spiegherebbe i lunghi tempi di richiesta. Sembra che questa funzionalità apparirà in pag.10
Jerome WAGNER

@JeromeWAGNER - Fantastico
J-DawG

Risposte:


7

Se usi use_remote_estimateassicurati di eseguire ANALYZE sul tavolo esterno (vedo stime abbastanza vicine con il reso, probabilmente l'avresti fatto). Inoltre, i miglioramenti pushdown non sono disponibili nella versione <9.5. Suppongo anche che tu abbia la stessa struttura di tabella sul server remoto (inclusi gli indici). Se è necessaria una bitmap a causa della bassa cardinalità, non utilizzerà l'indice a causa delle limitazioni sul meccanismo di pushdown. È possibile che si desideri ridurre la quantità di righe restituite per forzare una scansione dell'indice BTREE ( intervalli di data / ora). Sfortunatamente, non esiste un modo pulito per evitare SeqScan sul server remoto se il filtro restituisce + 10% delle righe della tabella (può variare questa percentuale se il pianificatore ritiene che la scansione dell'intera tabella sia più economica della ricerca delle letture). Se stai usando SSD, probabilmente ti sarà utile modificare random_page_cost).

È possibile utilizzare CTE per isolare il comportamento GROUP BY:

WITH atable AS (
    SELECT "IncidentTypeCode"
    FROM PUBLIC ."IntterraNearRealTimeUnitReflexes300s"
    WHERE 
       ("IncidentDateTime" 
              BETWEEN '2016-05-01 00:00:00'::TIMESTAMP WITHOUT TIME ZONE 
                  AND '2016-05-02 00:00:00'::TIMESTAMP WITHOUT TIME ZONE)
)
SELECT atable."IncidentTypeCode", COUNT(atable.IncidentTypeCode) 
FROM atable
GROUP BY atable."IncidentTypeCode" 
ORDER BY atable."IncidentTypeCode";

1
Le prestazioni sono state le stesse utilizzando il CTE. Proverà comunque le impostazioni random_page_cost. Grazie!
J-DawG,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.