Ich kann PostGIS 2.1 unter PostgreSQL 9.3.5 nicht zum Laufen bringen, um selbst für die einfachsten Abfragen einen räumlichen Index zu verwenden. Der gesamte Datensatz umfasst 8 Millionen Punkte (Bevölkerungszahlraster von hier) . Die Tabelle wird erstellt als
CREATE TABLE points (
population DOUBLE PRECISION NOT NULL,
location GEOGRAPHY(4326, POINT) NOT NULL
)
CREATE INDEX points_gix ON points USING GIST(location);
Die Abfragen sind so einfach wie möglich
SELECT SUM(population)
FROM points
WHERE ST_Distance(
location,
ST_GeographyFromText('SRID=4326; POINT(0 0)')
) < 1000
PostgreSQL verwendet dafür immer den Seq-Scan. Ich habe eine Teilmenge mit 10000 Punkten ausprobiert - immer noch den Seq-Scan. Irgendwelche Ideen?
Antworten:
ST_Distance berechnet tatsächlich den Abstand zwischen allen Punktpaaren, sodass kein Index verwendet werden kann. Ihre Abfrage führt also einen Sequenzscan durch und wählt dann die Geometrien aus, die kleiner sind als der von Ihnen angegebene Abstand. Sie suchen nach ST_DWithin , das einen Index verwendet.
ST_Distance ist nützlicher für die Bestellung von Ergebnissen, häufig in Verbindung mit ORDER BY und / oder LIMIT, die mit Abfragen erhalten wurden, die einen Index verwenden.
quelle
Wie @ JohnPowellakaBarça sagte,
ST_DWithin()
ist der richtige Weg, wenn Sie Korrektheit wollen .In meinem Fall möchte ich jedoch nur eine grobe Schätzung, sodass diese
ST_DWithin()
für meine Anforderungen sogar zu teuer (in Bezug auf die Abfragekosten) war. Ich habe stattdessen&&
undST_Expand(box2d)
(nicht mit dergeometry
Version verwechseln) verwendet. Beispiel:Was sofort offensichtlich sein wird, ist, dass es sich um Grad statt Meter handelt und wir einen Begrenzungsrahmen anstelle eines Kreises in einem Sphäroid verwenden. Für meinen Anwendungsfall reduziert sich dies von 24 ms auf nur 2 ms (lokal in SSD). Für meine Produktionsdatenbank in AWS RDS PostgreSQL mit gleichzeitigen Verbindungen und kaum großzügigen IOPS-Kontingenten (100 IOPS) gibt die ursprüngliche
ST_DWithin()
Abfrage jedoch zu viel IOPS aus und kann über 2000 ms und viel schlimmer ausgeführt werden, wenn das IOPS-Kontingent erschöpft ist.Dies ist nicht jedermanns Sache, aber falls Sie eine gewisse Genauigkeit für die Geschwindigkeit opfern können (oder um IOPS zu sparen), ist dieser Ansatz möglicherweise für Sie. Wie Sie in den folgenden Abfrageplänen sehen können, ist
ST_DWithin
zusätzlich zu Recheck Cond weiterhin ein räumlicher Filter im Bitmap-Heap-Scan erforderlich, während&&
für eine Box-Geometrie kein Filter erforderlich ist und nur Recheck Cond verwendet wird.Mir ist auch aufgefallen, dass es darauf
IS NOT NULL
ankommt, ohne dass Sie einen schlechteren Abfrageplan haben. Es scheint, dass der GIST-Index dafür nicht "klug genug" ist. (Natürlich wird es nicht benötigt, wenn Ihre Kolumne istNOT NULL
, in meinem Fall ist es in derNULL
Lage)20000 Zeilentabelle
ST_DWithin(geography, geography, 100000, FALSE)
auf AWS RDS 512 MB RAM mit 300 IOPS:20000 Zeilentabelle
&&
undST_Expand(box2d)
auf AWS RDS 512 MB RAM mit 300 IOPS:Wieder mit einfacherer Abfrage:
20000 Zeilentabelle
ST_DWithin(geography, geography, 100000, FALSE)
auf AWS RDS 512 MB RAM mit 300 IOPS:20000 Zeilentabelle
&&
undST_Expand(box2d)
auf AWS RDS 512 MB RAM mit 300 IOPS:quelle