Jeśli możesz ograniczyć maksymalną odległość między Twoimi miastami a Twoją lokalną pozycją, skorzystaj z faktu, że jedna minuta szerokości geograficznej (północ - południe) to jedna mila morska.
Umieść indeks w tabeli szerokości geograficznych.
Zrób sobie zapisaną funkcję hasrsine(lat1, lat2, long1, long2, unit) z formuły hasrsine pokazanej w twoim pytaniu. Zobacz poniżej
Następnie zrób to, biorąc pod uwagę moją szerokość geograficzną, moją długość geograficzną i mykm.
SELECT *
from cities a
where :mylatitude >= a.latitude - :mykm/111.12
and :mylatitude <= a.latitude + :mykm/111.12
and haversine(:mylatitude,a.latitude,:mylongitude,a.longitude, 'KM') <= :mykm
order by haversine(:mylatitude,a.latitude,:mylongitude,a.longitude, 'KM')
Spowoduje to użycie ramki ograniczającej szerokości geograficznej, aby z grubsza wykluczyć miasta, które są zbyt daleko od twojego punktu. Twój DBMS użyje skanowania zakresu indeksu w indeksie szerokości geograficznej, aby szybko wybrać wiersze w tabeli miast, które warto rozważyć. Następnie uruchomi twoją funkcję haversine, tę z wszystkimi obliczeniami sinusowymi i cosinusowymi, tylko w tych wierszach.
Sugeruję szerokość geograficzną, ponieważ odległość naziemna długości geograficznej zmienia się wraz z szerokością geograficzną.
Zauważ, że to jest prymitywne. Jest w porządku dla wyszukiwarki sklepów, ale nie używaj jej, jeśli jesteś inżynierem budownictwa — Ziemia ma kształt eliptyczny, a to zakłada, że jest kołowa.
(Przepraszam za magiczną liczbę 111,12. Jest to liczba km na stopniu szerokości geograficznej, czyli w sześćdziesięciu milach morskich.)
Zobacz tutaj praktyczną funkcję odległości.
Dlaczego ta funkcja przechowywana w MySQL daje inne wyniki niż wykonywanie obliczeń w zapytaniu?