2011-02-13 128 views
1

使用Maxmind的GeoIP軟件,我們可以在80%的時間內將IP地址的LONG/LAT縮小到25英里以內的相對精度。匹配最接近的經度/緯度

現在,我們不想使用MaxMind提供的任何其他信息,因爲執行查找的功能名稱(即城市)之間存在很多差異。如果其他方法無法找到某個功能,我們計劃嘗試進行查找,但出於性能方面的原因,查看浮動內容比字符串快得多。

現在,我對如何從Maxmind找到最接近的匹配LAT/LONG到我們的數據庫有點無知。問題是,與Maxmind相比,我們的數據庫特徵具有更高的精度,因此直接比較可能無效。如果我們嘗試在查詢期間向列應用ROUND(),那顯然會很慢。

給出下面的數據,會以最快的方式僅僅是像

LONG 79.93213 LAT 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中有一些新的空間存儲類型,或許任何人都可以提供超出我自己似乎忍受的障礙的解決方案。

+0

本帖](http://lists.mysql.com/mysql/204782)關於MySQL的網站可能會有所幫助一些實現(特別提到經/緯度座標)。 – 2011-02-13 02:51:51

回答

8

優雅(更準確)這樣的方式(但不是超快

// 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; 

編輯

這是Haversine formula從地理座標計算圓的距離。下面是這個公式的different platforms

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 
+0

我們已經實現了一個解決方案,類似於我已發佈的解決方案,但將我們的2.5M功能db的子集用於更易於管理的內容。然而,因爲這是我所要求的,如果你能解釋你使用的常數,我會接受你的答案。謝謝。 – 2011-02-18 14:27:02