Si puedes limitar la distancia máxima entre tus ciudades y tu posición local, aprovecha que un minuto de latitud (norte - sur) es una milla náutica.
Pon un índice en tu tabla de latitud.
Conviértase en una función almacenada haversine (lat1, lat2, long1, long2, unit) de la fórmula haversine que se muestra en su pregunta. Ver más abajo
Entonces haz esto, dada milatitud, milongitud y mikm.
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')
Esto usará un cuadro delimitador de latitud para descartar crudamente las ciudades que están demasiado lejos de su punto. Su DBMS utilizará un escaneo de rango de índice en su índice de latitud para seleccionar rápidamente las filas en su tabla de ciudades que vale la pena considerar. Luego ejecutará su función haversine, la que tiene todas las matemáticas de seno y coseno, solo en esas filas.
Sugiero latitud porque la distancia de longitud sobre el terreno varía con la latitud.
Tenga en cuenta que esto es crudo. Está bien para un buscador de tiendas, pero no lo use si es ingeniero civil:la tierra tiene una forma elíptica y esto supone que es circular.
(Perdón por el número mágico 111,12. Ese es el número de km en un grado de latitud, es decir, en sesenta millas náuticas).
Vea aquí una función de distancia factible.