sql >> Base de Datos >  >> RDS >> PostgreSQL

La consulta por coordenadas tarda demasiado - ¿opciones para optimizar?

Será mucho mejor usar un índice espacial que use un árbol R (esencialmente un índice bidimensional, que opera dividiendo el espacio en cajas), y funcionará mucho mejor que comparaciones mayores que, menores que en dos lat separados , lon valores en este tipo de consulta. Sin embargo, primero deberá crear un tipo de geometría, que luego indexará y usará en su consulta en lugar de los pares separados de latitud/longitud que está usando actualmente.

Lo siguiente creará un tipo de geometría, lo completará y le agregará un índice, asegurándose de que sea un punto y en latitud/longitud, conocido como 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);

Luego puede ejecutar la siguiente consulta para obtener sus eventos, que utilizarán intersecciones espaciales, que deberían utilizar su índice espacial:

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;

Usted crea el cuadro delimitador para su intersección utilizando ST_MakeBOX2D con dos conjuntos de puntos, que estarán en las esquinas diagonales del cuadro delimitador, por lo que los pares SW y NE o NW y SE funcionarían.

Cuando ejecute la explicación sobre esto, debería encontrar que el índice espacial está incluido. Esto funcionará mucho mejor que dos índices separados en las columnas lon y lat, ya que solo está alcanzando uno indexado, optimizado para la búsqueda espacial, en lugar de dos árboles B. Me doy cuenta de que esto representa otra forma de hacerlo y no responde a su pregunta original, excepto indirectamente.

EDITAR: Mike T ha señalado muy bien que para las búsquedas de cuadro delimitador en 4326, es más apropiado y más rápido usar un tipo de datos de geometría y el operador &&como SRID se ignorará de todos modos, por ejemplo,

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