Соответствие ближайшей долготе / широте - PullRequest
1 голос
/ 13 февраля 2011

Используя программное обеспечение Maxmind GeoIP, мы можем сузить LONG / LAT IP-адреса с относительной точностью в пределах 25 миль примерно в 80% случаев.

Теперь мы не хотим использовать какую-либо другую информацию, предоставленную MaxMind, потому что есть много расхождений между именами объектов, то есть городами, для поиска. Мы планируем попытаться выполнить такой поиск, если другие методы не смогут найти объект, но по соображениям производительности поиск по числам с плавающей запятой выполняется намного быстрее, чем строки.

Теперь я немного не понимаю, как мы можем найти наиболее близкое соответствие LAT / LONG, данное Maxmind нашей базе данных. Проблема в том, что наши возможности базы данных имеют гораздо более высокую точность по сравнению с Maxmind, поэтому прямое сравнение может быть неэффективным. Если мы попробуем применить ROUND () к столбцу во время запроса, это, очевидно, будет очень медленным.

Учитывая следующие данные, самый быстрый способ будет просто что-то вроде

ДОЛГО 79.93213 ЛАТ 39.13111

SELECT `feature_name` FROM `geo_features`
WHERE long BETWEEN 79.93 AND 79.79.94
AND lat BETWEEN 39.13 AND 39.14

Может ли кто-нибудь изящное решение, которое будет быстро вспыхивать? Я знаю, что в MySQL 5 есть несколько новых типов пространственного хранения, возможно, кто-нибудь может предложить решение, выходящее за рамки того, что я, похоже, поставил перед собой.

1 Ответ

8 голосов
/ 18 февраля 2011

Элегантный ( более точный ) способ сделать это (, но не слишком быстро )

// Closest within radius of 25 Miles
// 37, -122 are your current coordinates
// To search by kilometers instead of miles, replace 3959 with 6371
SELECT feature_name, 
 ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) 
  * cos( radians( long ) - radians(-122) ) + sin( radians(37) ) 
  * sin( radians( lat ) ) ) ) AS distance 
FROM geo_features HAVING distance < 25 
ORDER BY distance LIMIT 1;

Редактировать

Это формула Хаверсайна для расчета кругового расстояния от гео-координат.Вот некоторые реализации этой формулы в различных платформах

R = earth’s radius (mean radius = 6,371km)
Δlat = lat2− lat1
Δlong = long2− long1
a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
c = 2.atan2(√a, √(1−a))
d = R.c
// Note that angles need to be in radians to pass to Trigonometric functions
...