PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

A consulta por coordenadas demora muito - opções para otimizar?


Você ficará muito melhor usando um índice espacial que usa uma árvore R (essencialmente um índice bidimensional, que opera dividindo o espaço em caixas) e terá um desempenho muito melhor que maior que, menor que comparações em duas lats separadas , lon valores nesse tipo de consulta. Você precisará criar um tipo de geometria primeiro, que você indexa e usa em sua consulta em vez dos pares separados de lat/lon que você está usando no momento.

O seguinte irá criar um tipo de geometria, preenchê-lo e adicionar um índice a ele, garantindo que seja um ponto e em lat/lon, conhecido 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);

Em seguida, você pode executar a seguinte consulta para obter seus eventos, que usarão uma interseção espacial, que deverá utilizar seu í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;

Você faz a caixa delimitadora para sua interseção usando ST_MakeBOX2D com dois conjuntos de pontos, que estarão nos cantos diagonais da caixa delimitadora, para que os pares SW e NE ou NW e SE funcionem.

Ao executar a explicação sobre isso, você deve descobrir que o índice espacial está incluído. Isso terá um desempenho muito melhor do que dois índices separados nas colunas lon e lat, pois você está atingindo apenas um indexado, otimizado para pesquisa espacial, em vez de duas árvores B. Percebo que isso representa outra maneira de fazê-lo e não responde à sua pergunta original, exceto indiretamente.

EDITAR: Mike T destacou que para pesquisas de caixa delimitadora em 4326, é mais apropriado e mais rápido usar um tipo de dados de geometria e o operador &&, pois o SRID será ignorado de qualquer maneira, por exemplo,
 where ST_MakeBox2D(ST_MakePoint(swLon, swLat), ST_MakePoint(neLon, neLat)) && geom