J'essaie d'améliorer les performances de la requête ci-dessous. Peu importe comment j'écris la requête (sous-requête dans la clause FROM, sous-requête dans la clause WHERE) postgres insiste pour exécuter toutes les ~ 570K lignes via la fonction coûteuse ST_DWITHIN même s'il n'y a que 60 lignes où county = 24. Comment puis-je faire filtrer les postgres sur comté = 24 AVANT de parcourir la fonction postgis qui me semble beaucoup plus rapide et beaucoup plus efficace? 700 ms n'est pas trop préoccupant, mais à mesure que ce tableau atteint 10M +, je suis préoccupé par les performances.
À noter également, p.id est une clé primaire, p.zipcode est un index fk, z.county est un index fk et p.geom a un index GiST.
Requete:
EXPLAIN ANALYZE
SELECT count(p.id)
FROM point AS p
LEFT JOIN zipcode AS z
ON p.zipcode = z.zipcode
WHERE z.county = 24
AND ST_DWithin(
p.geom,
ST_SetSRID(ST_Point(-121.479756008715,38.563236291512),4269),
16090.0,
false
)
EXPLIQUEZ L'ANALYSE:
Aggregate (cost=250851.91..250851.92 rows=1 width=4) (actual time=724.007..724.007 rows=1 loops=1)
-> Hash Join (cost=152.05..250851.34 rows=228 width=4) (actual time=0.359..723.996 rows=51 loops=1)
Hash Cond: ((p.zipcode)::text = (z.zipcode)::text)
-> Seq Scan on point p (cost=0.00..250669.12 rows=7437 width=10) (actual time=0.258..723.867 rows=63 loops=1)
Filter: (((geom)::geography && '0101000020AD10000063DF8B52B45E5EC070FB752018484340'::geography) AND ('0101000020AD10000063DF8B52B45E5EC070FB752018484340'::geography && _st_expand((geom)::geography, 16090::double precision)) AND _st_dwithin((g (...)
Rows Removed by Filter: 557731
-> Hash (cost=151.38..151.38 rows=54 width=6) (actual time=0.095..0.095 rows=54 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 3kB
-> Bitmap Heap Scan on zipcode z (cost=4.70..151.38 rows=54 width=6) (actual time=0.023..0.079 rows=54 loops=1)
Recheck Cond: (county = 24)
Heap Blocks: exact=39
-> Bitmap Index Scan on fki_zipcode_county_foreign_key (cost=0.00..4.68 rows=54 width=0) (actual time=0.016..0.016 rows=54 loops=1)
Index Cond: (county = 24)
Planning time: 0.504 ms
Execution time: 724.064 ms
pointlignes où county = 24 dans une nouvelle table, la requête ne prend que 0,453 ms par rapport à 724, il y a donc certainement une grande différence.
count(*)comme une question de style. Si idc'est un pkid comme vous le dites, c'est ce NOT NULLqui signifie qu'ils sont les mêmes. Sauf count(id)a l'inconvénient que vous devez poser cette question si idest annulable.