Ако можете да ограничите максималното разстояние между вашите градове и местната ви позиция, възползвайте се от факта, че една минута географска ширина (север - юг) е една морска миля.
Поставете индекс във вашата таблица с географски ширини.
Направете си съхранена функция за хаверсинус (lat1, lat2, long1, long2, unit) от формулата за хаверсинус, показана във вашия въпрос. Вижте по-долу
След това направете това, като се има предвид mylatitude, mylongitude и 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')
Това ще използва поле за ограничаване на географската ширина, за да изключи грубо градове, които са твърде далеч от вашата точка. Вашата СУБД ще използва сканиране на обхвата на индекса на вашия индекс за географска ширина, за да избере бързо редовете в таблицата на вашите градове, които си струва да бъдат разгледани. След това ще изпълни функцията ви хаверсинус, тази с всички математически изчисления за синус и косинус, само на тези редове.
Предлагам географска ширина, защото разстоянието на земната дължина варира в зависимост от географската ширина.
Имайте предвид, че това е грубо. Добре е за търсач на магазини, но не го използвайте, ако сте строителен инженер - земята има елипсовидна форма и това предполага, че е кръгла.
(Съжалявам за магическото число 111.12. Това е броят км в градус географска ширина, което е в шестдесет морски мили.)
Вижте тук за работеща функция за разстояние.