Pertama beberapa komentar...
Saya telah melihat lusinan (bukan jutaan) implementasi di sini dan di forum lain; milikmu lebih baik dari kebanyakan.
Menurut salah satu sumber data (yang kebetulan saya unduh) ada sekitar 3,2 juta kota di dunia.
Untuk kinerja, Anda harus menghindari memeriksa semua baris 3M. Anda telah membuat awal yang baik dengan kotak pembatas yang berkembang. Perhatikan bahwa Anda harus memiliki
INDEX(lat, lon),
INDEX(lon, lat)
Pengoptimal akan memilih antara kueri tersebut dan kueri pertama (dengan COUNT(*)
) akan melihatnya sebagai 'penutup'. Ini akan menjadi garis di seluruh dunia atau irisan; peningkatan yang pasti atas baris 3M. Garis lintang terburuk (+34 derajat) memiliki 96 ribu kota di dalamnya. (1 derajat =69 mil / 111 km.) Untuk sepersepuluh derajat, 34,4 adalah yang terburuk, dengan 10 ribu kota.
(Ya, saya menikmati teka-teki data semacam ini.)
Dan, saya melihat bahwa Anda menangani garis tanggal dan kutub. Saya tidak berpikir Anda dapat memperbaikinya dengan menjadikan mereka sebagai kasus khusus.
(Saya hanya melihat rumus dan konstanta.)
Bantuan pengindeksan Geohash dan Z-order. Tetapi mereka memiliki masalah karena Anda perlu memeriksa hingga 4 area di sekitar target -- Ini seperti tidak menyadari bahwa bilangan bulat 199999 dan 200000 sangat dekat satu sama lain, meskipun digit pertama masing-masing berbeda.
"User pass dalam kode pos atau nama kota" -- itu adalah kueri titik ke salah satu dari dua tabel sederhana. (Kecuali bahwa mungkin ada dups -- lebih dari 320 masing-masing "san jose" dan "san antonio". Jauh di bawah daftar adalah nama non-Spanyol pertama:"victoria", dengan hanya 144 kota.)
Kedua, implementasi saya... (Ini memiliki beberapa kesamaan dengan milik Anda.)
http://mysql.rjweb.org/doc.php/latlng
Ini meningkatkan kinerja dengan menggunakan PARTITIONing
untuk menjaga kotak pembatas menjadi kira-kira persegi, bukan garis atau irisan. Jika Anda mencari 5 terdekat, algoritme saya jarang menyentuh lebih dari beberapa lusin baris, dan baris tersebut akan 'berkelompok' dalam sejumlah kecil blok, sehingga menjaga jumlah hit disk sangat rendah.
Hal penting dalam desain saya adalah memiliki semua kolom yang diperlukan dalam satu tabel. Setelah Anda menemukan 5 terdekat, Anda dapat pergi ke meja lain untuk mendapatkan hal-hal tambahan (nomor telepon, dll).
Untuk kode pos, ubah menjadi lat/lon sebelum memulai pencarian 5 terdekat.
Penggabungan di dalam algoritme kemungkinan besar akan merusak kinerja.