Prima alcuni commenti...
Ho visto dozzine (non milioni) di implementazioni qui e su altri forum; il tuo è migliore della maggior parte.
Secondo una fonte di dati (che ho scaricato) ci sono circa 3,2 milioni di città nel mondo.
Per le prestazioni, è necessario evitare di controllare tutte le righe 3M. Hai fatto un buon inizio con il riquadro di delimitazione in crescita. Nota che dovresti avere
INDEX(lat, lon),
INDEX(lon, lat)
L'Ottimizzatore sceglierà tra quelli e la prima query (con il COUNT(*)
) lo vedranno come 'copertura'. Sarà una striscia intorno al globo o un cuneo; un netto miglioramento rispetto alle righe 3M. La peggiore latitudine (+34 gradi) ha 96.000 città. (1 grado =69 miglia / 111 km.) Per un decimo di grado, 34,4 è il peggiore, con 10.000 città.
(Sì, mi piace questo tipo di puzzle di dati.)
E vedo che gestisci la linea della data e i poli. Non credo che tu possa migliorare avendoli come un caso speciale.
(Ho solo dato un'occhiata alle formule e alle costanti.)
Guida all'indicizzazione di Geohash e Z-order. Ma hanno un inconveniente in quanto è necessario controllare fino a 4 aree intorno all'obiettivo:è come non rendersi conto che i numeri interi 199999 e 200000 sono molto vicini tra loro, nonostante la prima cifra di ciascuno sia diversa.
"L'utente passa il codice postale o il nome della città" - questa è una query puntuale in una delle due semplici tabelle. (Tranne che ci possono essere dups -- oltre 320 ciascuno di "san jose" e "san antonio". Abbastanza in fondo alla lista c'è il primo nome non spagnolo:"victoria", con solo 144 città.)
In secondo luogo, la mia implementazione... (Ha alcune somiglianze con la tua.)
http://mysql.rjweb.org/doc.php/latlng
Ciò migliora le prestazioni utilizzando PARTITIONing
per mantenere il riquadro di delimitazione all'incirca a un quadrato, invece di una striscia o di un cuneo. Se stai cercando le 5 più vicine, il mio algoritmo raramente toccherà più di qualche dozzina di righe e quelle righe saranno "raggruppate" in un piccolo numero di blocchi, mantenendo così il numero di hit del disco molto basso.
Una cosa fondamentale nel mio progetto è avere tutte le colonne necessarie in un'unica tabella. Una volta trovati i 5 più vicini, puoi passare ad altri tavoli per ottenere cose accessorie (numero di telefono, ecc.).
Per quanto riguarda i codici postali, trasformali in lat/lon prima di iniziare la ricerca dei 5 più vicini.
È molto probabile che un join all'interno dell'algoritmo distrugga le prestazioni.