les performances de postgres_fdw sont lentes


12

La requête suivante sur un étranger prend environ 5 secondes pour s'exécuter sur 3,2 millions de lignes:

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

Lorsque j'exécute la même requête sur une table normale, elle revient en 0,6 seconde. Les plans d'exécution sont assez différents:

Table 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

Table étrangère

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

Je pense que je paie un prix élevé pour la GROUP BYclause, qui n'est pas transmise au serveur étranger lorsque je EXPLAIN VERBOSE:

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

Cela renvoie 700k lignes. Y a-t-il un moyen de contourner ceci?

Hier, j'ai passé beaucoup de temps à lire cette page de documentation et j'ai pensé avoir trouvé ma réponse en définissant use_remote_estimatetrue, mais cela n'a eu aucun effet.

J'ai accès au serveur étranger pour créer des objets si nécessaire. La valeur d'horodatage dans la WHEREclause peut être n'importe quoi; il ne provient pas d'une liste de valeurs prédéfinies.


3
Il y a quelques améliorations du pushdown dans 9.6 qui pourraient être intéressantes: wiki.postgresql.org/wiki/NewIn96#postgres_fdw
Jack dit d'essayer topanswers.xyz le

Lorsque vous dites table normale vs table étrangère, exécutez-vous sur la même table (localement et à distance) ou réellement sur des tables différentes (elles se lisent comme si elles l'étaient), si elles sont différentes, vérifiez l'indexation sur le serveur distant assurez-vous qu'elles sont les mêmes comme vous semblez lire les sources d'information complètement différentes par IntterraNearRealTimeUnitReflexes300sForeignrapport IntterraNearRealTimeUnitReflexes300set idx_incident_date_time_300 je suppose que ceux de 300s sont les mêmes, mais il pourrait être vérifier en valeur si l' idx_incident_date_time_300index existe sur le serveur étranger
Ste Bov

2
D'après ce que je comprends, les agrégats (COUNT) ne sont pas poussés vers le serveur distant, ce qui expliquerait le long temps de demande. Il semble que cette fonctionnalité apparaîtra dans la page 10 - depesz.com/2016/10/25/…
Jerome WAGNER

@JeromeWAGNER - Génial
J-DawG

Réponses:


7

Si vous utilisez use_remote_estimateassurez-vous d'exécuter ANALYSER la table étrangère (je vois des estimations assez proches de celles retournées, vous l'auriez probablement fait). De plus, les améliorations du menu déroulant ne sont pas disponibles dans la version <9.5. Je suppose également que vous avez la même structure de table sur le serveur distant (y compris les index). Si un bitmap est nécessaire en raison de la faible cardinalité, il n'utilisera pas l'index en raison des limitations du mécanisme de refoulement. Vous souhaiterez peut-être réduire le nombre de lignes renvoyées pour forcer une analyse d'index BTREE ( plages d'horodatage). Malheureusement, il n'existe aucun moyen propre d'éviter le SeqScan sur le serveur distant si le filtre renvoie + 10% des lignes de la table (peut varier ce pourcentage si le planificateur considère que l'analyse de la table entière est moins chère que la recherche de lectures). Si vous utilisez SSD, vous trouverez probablement utile de modifier random_page_cost).

Vous pouvez utiliser CTE pour isoler le comportement 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
Les performances étaient les mêmes avec le CTE. Essaiera cependant les paramètres random_page_cost. Merci!
J-DawG
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.