Estou criando um aplicativo que deveria consultar e retornar todos os dados Record
de uma tabela a X
quilômetros de distância PointX
. Records
e PointX
as posições dos s são determinadas a partir de (long/lat)
informações fornecidas pelo Google Geocode API.
Eu sou novo no PostGIS. Após uma pesquisa rápida, encontrei esta pergunta . A resposta parece estar na linha de:
SELECT *
FROM your_table
WHERE ST_Distance_Sphere(the_geom, ST_MakePoint(your_lon,your_lat)) <= radius_mi * 1609.34
O problema é: mesmo que eu esteja apenas começando no GIS, quando olho para a consulta acima, não consigo imaginar como isso pode usar um índice. Existem 2 chamadas de função. Eu imagino a tabela sendo digitalizada para todos Record
. Eu quero estar errado :)
Pergunta: O PostGIS tem algum tipo de índice capaz de tornar o desempenho da consulta acima? Caso contrário, qual seria a abordagem recomendada para fazer o que eu preciso?
fonte
ST_SetSRID()
naST_MakePoint
conversão antes da geografia na consulta.Respostas:
Existem duas chaves para obter um bom desempenho da consulta geodésica com tabelas grandes com
geometry
colunas usando dados geográficos WGS 1984 (SRID 4326):ST_DWithin
função, que pesquisa usando um índice espacial disponível, e encontrará recursos geográficos com uma distância cartesianaST_DWithin
poder usá-loEntão, vamos ver o que acontece no mundo real. Primeiro, precisamos criar e preencher uma tabela de um milhão de pontos aleatórios:
Se executarmos a consulta ST_Distance, obteremos sua verificação de tabela completa esperada:
Agora, se usarmos
ST_DWithin
, ainda temos uma verificação completa da tabela (embora mais rápida):E esta é a última peça - Construindo o índice de cobertura (geografia do elenco):
Finalmente, o otimizador está usando o índice espacial e mostra, mas quais são as três ordens de grandeza entre amigos?
Algumas advertências:
Como eu sou um nerd de banco de dados, meu PC doméstico tem 16Gb de RAM, seis núcleos de 3,3Ghz e um SSD de 256Gb para o espaço de tabela padrão do banco de dados; sua milhagem pode variar
Executei novamente o SQL de criação antes de cada consulta, para nivelar o campo de jogo em relação às páginas "quentes" no cache, mas isso poderia produzir resultados ligeiramente diferentes porque a mesma semente aleatória não foi usada para execuções diferentes
E uma nota:
fonte