Ich versuche, die Leistung für die folgende Abfrage zu verbessern. Unabhängig davon, wie ich die Abfrage schreibe (Unterabfrage in der FROM-Klausel, Unterabfrage in der WHERE-Klausel), besteht postgres darauf, alle ~ 570K-Zeilen durch die teure ST_DWITHIN-Funktion auszuführen, obwohl es nur 60 Zeilen gibt, in denen county = 24 ist. Wie kann ich Postgres dazu bringen, nach County = 24 zu filtern, bevor ich die Postgis-Funktion durchlaufe, die meiner Meinung nach viel schneller und weitaus effizienter ist? 700 ms sind kein Grund zur Sorge, aber da diese Tabelle auf 10 Millionen + anwächst, mache ich mir Sorgen um die Leistung.
Zu beachten ist auch, dass p.id ein Primärschlüssel ist, p.zipcode ein fk-Index ist, z.county ein fk-Index ist und p.geom einen GiST-Index hat.
Abfrage:
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
)
ANALYSE ERKLÄREN:
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
Zeilen, in denen Grafschaft = 24 ist, alleine in eine neue Tabelle kopiere, dauert die Abfrage nur 0,453 ms im Vergleich zu 724, sodass es definitiv einen großen Unterschied gibt.
count(*)
als eine Frage des Stils verwenden. Wenn id
es sich um ein pkid handelt, wie Sie sagen, NOT NULL
bedeutet dies, dass sie gleich sind. Außer count(id)
hat den Nachteil, dass Sie diese Frage stellen müssen, wenn id
nullbar ist.