Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Qual é a melhor abordagem para encontrar todos os endereços que estão a uma distância específica do ponto selecionado


Quando implementei isso no MySQL (para armazenar lugares em uma esfera oblata, que é basicamente o que a terra é (suponho que você esteja falando sobre a terra!)), armazenei o máximo possível de informações pré-calculadas no banco de dados. Portanto, para uma linha que armazena latitude e longitude , também calculo no momento da inserção os seguintes campos:
  • radiansLongitude (Math.toRadians(longitude) )
  • sinRadiansLatitude (Math.sin(Math.toRadians(latitude) )
  • cosRadiansLatitude (Math.cos(Math.toRadians(latitude) )

Então, quando eu pesquiso os lugares que estão dentro de X unidades da latitude /longitude em questão, minha declaração preparada é a seguinte:
from Location l where
    acos(
        sin(:latitude) * sinRadiansLatitude + 
        cos(:latitude) * cosRadiansLatitude * 
        cos(radiansLongitude - :longitude) 
        ) * YYYY < :distance
    and l.latitude>:minimumSearchLatitude
    and l.latitude<:maximumSearchLatitude 
    and l.longitude>:minimumSearchLongitude 
    and l.longitude<:maximumSearchLongitude 
    order by acos(
                sin(:latitude) * sinRadiansLatitude + 
                cos(:latitude) * cosRadiansLatitude * 
                cos(radiansLongitude - :longitude)  
        ) * YYYY asc

Onde YYYY =3965 fornece distâncias em milhas ou YYYY =6367 pode ser usado para distâncias em km.

Por fim, usei o maximumSearchLatitude / maximumSearchLongitude / minimumSearchLongitude / maximumSearchLongitude parâmetros para excluir a maioria dos pontos do conjunto de resultados antes que o banco de dados tenha que realizar quaisquer cálculos. Você pode ou não precisar disso. Se você usar isso, caberá a você quais valores escolher para esses parâmetros, pois dependerá do que você está pesquisando.

Obviamente, serão necessárias aplicações criteriosas de índices no banco de dados.

A vantagem de usar essa abordagem é que as informações que nunca mudam, mas são necessárias todas as vezes, são calculadas apenas uma vez, enquanto o cálculo dos valores de radiansLongitude , sinRadiansLatitude , cosRadiansLatitude para cada linha, toda vez que você realizar uma pesquisa, ficará muito caro muito rápido.

A outra opção é usar um índice geoespacial , o que significa que tudo isso é tratado para você pelo banco de dados. Eu não sei quão bem o Hibernate se integra com isso.

Isenção de responsabilidade:faz muito tempo desde que olhei para isso e não sou um especialista em GIS!