Đầu tiên, một số nhận xét ...
Tôi đã thấy hàng chục (không phải hàng triệu) việc triển khai ở đây và trên các diễn đàn khác; của bạn tốt hơn hầu hết.
Theo một nguồn dữ liệu (mà tôi tình cờ đã tải xuống), có khoảng 3,2 triệu thành phố trên thế giới.
Đối với hiệu suất, bạn cần tránh kiểm tra tất cả các hàng 3M. Bạn đã có một khởi đầu tốt với hộp giới hạn ngày càng tăng. Lưu ý rằng bạn nên có
INDEX(lat, lon),
INDEX(lon, lat)
Trình tối ưu hoá sẽ chọn giữa các truy vấn đó và truy vấn đầu tiên (với COUNT(*)
) sẽ xem đó là 'che phủ'. Nó sẽ là một sọc quanh hình cầu hoặc hình nêm; một sự cải tiến rõ ràng so với hàng 3M. Vĩ độ tồi tệ nhất (+34 độ) có 96K thành phố trong đó. (1 độ =69 dặm / 111 km.) Đối với một phần mười độ, 34,4 là mức tồi tệ nhất, với 10 nghìn thành phố.
(Vâng, tôi thích loại câu đố dữ liệu này.)
Và, tôi thấy rằng bạn xử lý đường dữ liệu và các cực. Tôi không nghĩ rằng bạn có thể cải thiện nếu có chúng như một trường hợp đặc biệt.
(Tôi chỉ xem qua các công thức và hằng số.)
Trợ giúp lập chỉ mục Geohash và Z-order. Nhưng chúng có một trục trặc ở chỗ bạn cần kiểm tra tới 4 khu vực xung quanh mục tiêu - Nó giống như việc không nhận ra rằng các số nguyên 199999 và 200000 thực sự gần nhau, mặc dù chữ số đầu tiên của mỗi số là khác nhau.
"Người dùng chuyển mã zip hoặc tên thành phố" - đó là truy vấn điểm vào một trong hai bảng đơn giản. (Ngoại trừ việc có thể có sai sót - hơn 320 mỗi "san jose" và "san antonio". Khá xa trong danh sách là cái tên không phải tiếng Tây Ban Nha đầu tiên:"victoria", chỉ có 144 thành phố.)
Thứ hai, việc triển khai của tôi ... (Nó có một số điểm tương đồng với của bạn.)
http://mysql.rjweb.org/doc.php/latlng
Điều này cải thiện hiệu suất bằng cách sử dụng PARTITIONing
để giữ cho hộp giới hạn xuống gần một hình vuông, thay vì một đường sọc hoặc hình nêm. Nếu bạn đang tìm 5 hàng gần nhất, thuật toán của tôi sẽ hiếm khi chạm vào nhiều hơn vài chục hàng và những hàng đó sẽ được 'nhóm' thành một số lượng nhỏ các khối, do đó giữ cho số lần truy cập đĩa rất thấp.
Một điều quan trọng trong thiết kế của tôi là có tất cả các cột cần thiết trong một bảng. Khi bạn đã tìm thấy 5 gần nhất, bạn có thể đi đến các bàn khác để lấy những thứ phụ trợ (số điện thoại, v.v.).
Đối với mã zip, hãy chuyển chúng thành vĩ độ / kinh độ trước khi bắt đầu tìm kiếm 5 mã gần nhất.
Một phép nối bên trong thuật toán rất có thể phá hủy hiệu suất.