Sto cercando di migliorare le prestazioni per la query di seguito. Indipendentemente da come scrivo la query (sottoquery nella clausola FROM, sottoquery nella clausola WHERE) postgres insiste sull'esecuzione di tutte le righe ~ 570K attraverso la costosa funzione ST_DWITHIN anche se ci sono solo 60 righe in cui county = 24. Come posso filtrare Postgres su county = 24 PRIMA di passare attraverso la funzione Postgis che mi sembra molto più veloce e molto più efficiente? 700ms non sono motivo di troppa preoccupazione, ma poiché questa tabella cresce a 10 M + sono preoccupato per le prestazioni.
Inoltre, p.id è una chiave primaria, p.zipcode è un indice fk, z.county è un indice fk e p.geom ha un indice GiST.
Query:
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
)
SPIEGARE ANALISI:
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
point
righe in cui county = 24 su una nuova tabella da sole, la query richiede solo .453ms rispetto a 724, quindi c'è sicuramente una grande differenza.
count(*)
come una questione di stile. Se id
è un pkid come dici tu, NOT NULL
significa che sono gli stessi. Tranne che count(id)
ha lo svantaggio che devi porre quella domanda se id
è nullable.