PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Abfrage nach Koordinaten dauert zu lange - Optimierungsmöglichkeiten?

Sie werden viel besser dran sein, einen räumlichen Index zu verwenden, der einen R-Baum verwendet (im Wesentlichen ein zweidimensionaler Index, der den Raum in Kästchen unterteilt) und weitaus besser abschneidet als größer als, kleiner als Vergleiche auf zwei separaten Lats , lon-Werte bei dieser Art von Abfrage. Sie müssen jedoch zuerst einen Geometrietyp erstellen, den Sie dann indizieren und in Ihrer Abfrage anstelle der separaten Lat/Lon-Paare verwenden, die Sie derzeit verwenden.

Im Folgenden wird ein Geometrietyp erstellt, gefüllt und ein Index hinzugefügt, um sicherzustellen, dass es sich um einen Punkt und in Breite/Länge handelt, bekannt als EPSG:4326

alter table event add column geom geometry(POINT, 4326);
update event set geom=ST_SetSrid(ST_MakePoint(lon, lat), 4326);
create index ix_spatial_event_geom on event using gist(geom);

Dann können Sie die folgende Abfrage ausführen, um Ihre Ereignisse abzurufen, die eine räumliche Schnittmenge verwenden, die Ihren räumlichen Index verwenden sollte:

Select * from events where ST_Intersects(ST_SetSRID(ST_MakeBox2D(ST_MakePoint(swLon, swLat), 
    ST_MakePoint(neLon, neLat)),4326), geom) 
order by relevancy desc limit 100;

Sie erstellen den Begrenzungsrahmen für Ihre Kreuzung, indem Sie ST_MakeBOX2D mit zwei Sätzen von Punkten verwenden, die sich an diagonalen Ecken des Begrenzungsrahmens befinden, sodass die SW- und NE- oder die NW- und SE-Paare beide funktionieren würden.

Wenn Sie "explain on this" ausführen, sollten Sie feststellen, dass der räumliche Index enthalten ist. Dies wird eine weitaus bessere Leistung erbringen als zwei separate Indizes für lon- und lat-Spalten, da Sie nur einen indizierten, optimierten für die räumliche Suche treffen, und nicht zwei B-Bäume. Mir ist klar, dass dies eine andere Möglichkeit darstellt und Ihre ursprüngliche Frage nur indirekt beantwortet.

BEARBEITEN: Mike T hat den sehr guten Punkt gemacht, dass es für Bounding-Box-Suchen in 4326 geeigneter und schneller ist, einen Geometriedatentyp und den &&-Operator zu verwenden, da die SRID ohnehin ignoriert wird, z. B.

 where ST_MakeBox2D(ST_MakePoint(swLon, swLat), ST_MakePoint(neLon, neLat)) && geom