Erstens , die Verwendung
ST_SetSRID(ST_MakePoint(c.longitude, c.latitude),4326)::geography
anstatt
ST_GeographyFromText('SRID=4326;POINT(' || c.longitude || ' ' || c.latitude || ')')
Pro Dokumentation:
ST_MakePoint
Nicht OGC-konform zu sein ist im Allgemeinen schneller und präziser als ST_GeomFromText
und ST_PointFromText
. Es ist auch einfacher zu verwenden, wenn Sie Rohkoordinaten anstelle von WKT haben.
Als nächstes wird die Abfrage kürzer zu machen und geben Sie nur Parameter suchen einmal (ohne viel Einfluss auf die Leistung), verwenden Sie eine Unterabfrage (oder CTE):
SELECT id
, ST_Distance(t.x
, ST_SetSRID(ST_MakePoint(c.longitude, c.latitude),4326)::geography) AS dist
FROM cafes c
, (SELECT ST_GeographyFromText('SRID=4326;POINT(-76.000000 39.000000)')) AS t(x)
WHERE ST_DWithin(t.x
, ST_SetSRID(ST_MakePoint(c.longitude, c.latitude),4326)::geography, 2000)
ORDER BY dist;
Schließlich benötigen Sie einen GiST-Index , um dies für große Tabellen schnell zu machen.
Per Dokumentation zuST_DWithin()
:
Dieser Funktionsaufruf enthält automatisch einen Begrenzungsrahmenvergleich, bei dem alle für die Geometrien verfügbaren Indizes verwendet werden.
Sie könnten dies mit einem Funktionsindex für den Ausdruck am Anfang der Antwort arbeiten lassen. Aber ich würde zunächst eine Typenspalte speichern geography
(nennen wir es thegeog
) und einen einfachen GiST-Index wie folgt erstellen:
CREATE INDEX cafes_thegeog_gist ON cafes USING gist(thegeog);
Zu dieser viel einfacheren und schnelleren Abfrage gelangen:
SELECT id, ST_Distance(t.x, thegeog) AS distance
FROM cafes c
, (SELECT ST_GeographyFromText('SRID=4326;POINT(-76.000000 39.000000)')) AS t(x)
WHERE ST_DWithin(t.x, thegeog, 2000)
ORDER BY distance;
Aktualisiert, um geography
mit geography
übereinzustimmen, wie von @ LR1234567 im Kommentar hervorgehoben. Alternativ können Sie mit arbeiten geometry
. Alle hier verwendeten Funktionen funktionieren für beide (außer fürST_MakePoint
die angehängte Besetzung). Was ist der Unterschied?
Wenn Sie die n nächstgelegenen Cafés stattdessen alle innerhalb eines Radius erhalten möchten , ziehen Sie eine Suche nach dem nächsten Nachbarn in Betracht . Oft bequemer.
WHERE
Klausel verwenden? Möchten Sie es mit einer Schwelle vergleichen?