Najpierw kilka komentarzy...
Widziałem dziesiątki (nie miliony) wdrożeń tutaj i na innych forach; twój jest lepszy niż większość.
Według jednego źródła danych (które akurat pobrałem) na świecie jest około 3,2 miliona miast.
Aby uzyskać wydajność, należy unikać sprawdzania wszystkich rzędów 3M. Zrobiłeś dobry start z rosnącą ramką ograniczającą. Pamiętaj, że powinieneś mieć
INDEX(lat, lon),
INDEX(lon, lat)
Optymalizator wybierze między tymi a pierwszym zapytaniem (z COUNT(*)
) uzna to za „przykrycie”. Będzie to pasek na całym świecie lub klin; zdecydowana poprawa w stosunku do 3M rzędów. Najgorsza szerokość geograficzna (+34 stopnie) ma w sobie 96 tys. miast. (1 stopień =69 mil / 111 km). Dla jednej dziesiątej stopnia 34,4 jest najgorsze, z 10 000 miast.
(Tak, lubię ten rodzaj układanki danych.)
I widzę, że zajmujesz się dataline i biegunami. Nie sądzę, aby można było je poprawić, mając je jako specjalny przypadek.
(Rzuciłem tylko okiem na wzory i stałe).
Pomoc w indeksowaniu Geohash i Z-order. Ale mają problem polegający na tym, że musisz sprawdzić do 4 obszarów wokół celu -- To tak, jakby nie zdawać sobie sprawy, że liczby całkowite 199999 i 200000 są naprawdę blisko siebie, mimo że pierwsza cyfra każdej z nich jest inna.
„Użytkownik podaje kod pocztowy lub nazwę miasta” — to zapytanie punktowe do jednej z dwóch prostych tabel. (Poza tym, że mogą być oszuści – po ponad 320 „san jose” i „san antonio”. Dość daleko na liście znajduje się pierwsza niehiszpańska nazwa:„victoria”, mająca tylko 144 miasta).
Po drugie, moja implementacja... (Ma pewne podobieństwa do twojego.)
http://mysql.rjweb.org/doc.php/latlng
Poprawia to wydajność dzięki użyciu PARTITIONing
do utrzymywania ramki ograniczającej mniej więcej do kwadratu, zamiast paska lub klina. Jeśli szukasz 5 najbliższych, mój algorytm rzadko będzie dotykał więcej niż kilkudziesięciu wierszy, a wiersze te będą „zgrupowane” w małej liczbie bloków, dzięki czemu liczba trafień dysku będzie bardzo niska.
Kluczową rzeczą w moim projekcie jest umieszczenie wszystkich niezbędnych kolumn w jednej tabeli. Po znalezieniu najbliższych 5 możesz przejść do innych stolików, aby uzyskać dodatkowe rzeczy (numer telefonu itp.).
Jeśli chodzi o kody pocztowe, zamień je na łat/dług. przed rozpoczęciem wyszukiwania 5 najbliższych.
Sprzężenie wewnątrz algorytmu najprawdopodobniej zniszczy wydajność.