Zunächst einige Kommentare...
Ich habe Dutzende (nicht Millionen) Implementierungen hier und in anderen Foren gesehen; Ihres ist besser als die meisten anderen.
Laut einer Datenquelle (die ich zufällig heruntergeladen habe) gibt es etwa 3,2 Millionen Städte auf der Welt.
Aus Leistungsgründen müssen Sie vermeiden, alle 3M-Zeilen zu überprüfen. Sie haben mit dem wachsenden Begrenzungsrahmen einen guten Anfang gemacht. Beachten Sie, dass Sie
haben solltenINDEX(lat, lon),
INDEX(lon, lat)
Der Optimierer wählt zwischen diesen und der ersten Abfrage (mit dem COUNT(*)
) wird dies als "Abdeckung" sehen. Es wird ein Streifen um den Globus oder ein Keil sein; eine deutliche Verbesserung gegenüber 3 Millionen Reihen. Der schlechteste Breitengrad (+34 Grad) hat 96.000 Städte. (1 Grad =69 Meilen / 111 km.) Für ein Zehntel Grad ist 34,4 der schlechteste Wert bei 10.000 Städten.
(Ja, ich mag diese Art von Datenpuzzle.)
Und wie ich sehe, kümmern Sie sich um die Datumsgrenze und die Stangen. Ich glaube nicht, dass Sie es verbessern können, sie als Sonderfall zu haben.
(Ich habe nur einen Blick auf die Formeln und Konstanten geworfen.)
Geohash und Indizierung in Z-Reihenfolge helfen. Aber sie haben einen Schluckauf, da Sie bis zu 4 Bereiche um das Ziel herum überprüfen müssen -- Es ist, als würde man nicht erkennen, dass die ganzen Zahlen 199999 und 200000 sehr nahe beieinander liegen, obwohl die erste Ziffer von jeder unterschiedlich ist.
„Benutzer gibt Postleitzahl oder Stadtnamen ein“ – das ist eine Punktabfrage in einer von zwei einfachen Tabellen. (Außer, dass es Dups geben kann – jeweils über 320 von „san jose“ und „san antonio“. Ziemlich weit unten auf der Liste steht der erste nicht-spanische Name:„victoria“, mit nur 144 Städten.)
Zweitens, meine Implementierung... (Es hat einige Ähnlichkeiten mit Ihrem.)
http://mysql.rjweb.org/doc.php/latlng
Dies verbessert die Leistung durch die Verwendung von PARTITIONing
um den Begrenzungsrahmen auf ungefähr ein Quadrat zu begrenzen, anstatt auf einen Streifen oder Keil. Wenn Sie nach den 5 nächsten suchen, wird mein Algorithmus selten mehr als ein paar Dutzend Zeilen berühren, und diese Zeilen werden in einer kleinen Anzahl von Blöcken "geclustert", wodurch die Anzahl der Festplattenzugriffe sehr gering gehalten wird.
Eine entscheidende Sache in meinem Design ist, alle notwendigen Spalten in einer Tabelle zu haben. Sobald Sie die nächsten 5 gefunden haben, können Sie zu anderen Tischen gehen, um zusätzliche Dinge (Telefonnummer usw.) zu erhalten.
Wandeln Sie die Postleitzahlen in Breitengrad/Längengrad um, bevor Sie mit der Suche nach den 5 nächstgelegenen beginnen.
Ein Join innerhalb des Algorithmus zerstört sehr wahrscheinlich die Performance.