Mysql
 sql >> Base de données >  >> RDS >> Mysql

Quelle est la meilleure approche pour trouver toutes les adresses qui se trouvent à une distance spécifique du point sélectionné

Lorsque j'ai implémenté cela dans MySQL (pour stocker des lieux sur une sphère oblate, qui est essentiellement ce qu'est la terre (je suppose que vous parlez de la terre !)), j'ai stocké autant d'informations pré-calculées que possible dans la base de données. Donc, pour une ligne qui stocke latitude et longitude , je calcule également au moment de l'insertion les champs suivants :

  • radiansLongitude (Math.toRadians(longitude) )
  • sinRadiansLatitude (Math.sin(Math.toRadians(latitude) )
  • cosRadiansLatitude (Math.cos(Math.toRadians(latitude) )

Ensuite, lorsque je recherche les lieux situés à moins de X unités de la latitude /longitude en question, ma déclaration préparée est la suivante :

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

YYYY =3965 vous donne les distances en miles ou YYYY =6367 peut être utilisé pour les distances en km.

Enfin, j'ai utilisé le maximumSearchLatitude / maximumSearchLongitude / minimumSearchLongitude / maximumSearchLongitude paramètres pour exclure la majorité des points du jeu de résultats avant que la base de données n'ait à effectuer des calculs. Vous pouvez ou non en avoir besoin. Si vous l'utilisez, ce sera à vous de choisir les valeurs que vous choisirez pour ces paramètres, car cela dépendra de ce que vous recherchez.

Évidemment, des applications judicieuses des index dans la base de données seront nécessaires.

L'avantage d'utiliser cette approche est que les informations qui ne changent jamais mais qui sont nécessaires à chaque fois ne sont calculées qu'une seule fois, alors que le calcul des valeurs de radiansLongitude , sinRadiansLatitude , cosRadiansLatitude pour chaque ligne chaque fois que vous effectuez une recherche va devenir très cher très rapidement.

L'autre option consiste à utiliser un index géospatial , ce qui signifie que tout cela est pris en charge pour vous par la base de données. Je ne sais pas dans quelle mesure Hibernate s'intègre à cela.

Avis de non-responsabilité :cela fait longtemps que je n'ai pas regardé cela, et je ne suis pas un expert en SIG !