Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jakie jest najlepsze podejście, aby znaleźć wszystkie adresy, które znajdują się w określonej odległości od wybranego punktu?

Kiedy zaimplementowałem to w MySQL (do przechowywania miejsc na spłaszczonej sferze, czyli w zasadzie tym, czym jest Ziemia (zakładam, że mówisz o Ziemi!)), zachowałem w bazie danych tyle wstępnie obliczonych informacji, ile to możliwe. Tak więc dla wiersza, który przechowuje latitude i longitude , obliczam również w czasie wstawiania następujące pola:

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

Następnie, gdy szukam miejsc, które znajdują się w obrębie X jednostek latitude /longitude moje przygotowane oświadczenie brzmi następująco:

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

Gdzie YYYY =3965 daje odległości w milach lub YYYY =6367 może być użyte dla odległości w km.

Wreszcie użyłem maximumSearchLatitude / maximumSearchLongitude / minimumSearchLongitude / maximumSearchLongitude parametry, aby wykluczyć większość punktów ze zbioru wyników, zanim baza danych będzie musiała wykonać jakiekolwiek obliczenia. Możesz tego potrzebować lub nie. Jeśli tego użyjesz, to od Ciebie zależy, jakie wartości wybierzesz dla tych parametrów, ponieważ będzie to zależeć od tego, czego szukasz.

Oczywiście konieczne będzie rozsądne stosowanie indeksów w bazie danych.

Zaletą tego podejścia jest to, że informacje, które nigdy się nie zmieniają, ale są potrzebne za każdym razem, są obliczane tylko raz, podczas gdy oblicza się wartości radiansLongitude , sinRadiansLatitude , cosRadiansLatitude za każdy wiersz za każdym razem, gdy przeprowadzasz wyszukiwanie, bardzo szybko stanie się bardzo drogi.

Inną opcją jest użycie indeksu geoprzestrzennego , co oznacza, że ​​wszystko to jest obsługiwane przez bazę danych. Nie wiem jednak, jak dobrze Hibernate się z tym integruje.

Zastrzeżenie:minęło dużo czasu, odkąd na to patrzyłem, a nie jestem ekspertem GIS!



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL - Warunek WHERE na SUM()

  2. Najlepsze praktyki dotyczące wydajnego przechowywania skrótów md5 w mysql

  3. COMMIT OR conn.setAutoCommit(true)

  4. Kiedy i dlaczego używać mysqli_fetch_row, mysqli_fetch_object, mysqli_fetch_assoc, mysqli_fetch_array

  5. Czy MySQL może zastąpić wiele znaków?