带有位置数据的大型MySQL DB(21MM记录) - 每个位置都有lat和long - 需要运行'附近'查询

时间:2011-07-29 02:33:26

标签: mysql geospatial spatial

我们有一个大的位置数据库 - 每行都指定了lat long。数据库托管在MySQL中。

我们需要运行两种类型的查询:

  • 附近的地方(按距离排序)
  • 按类别放置附近(类别为列)

随着记录数量的增加,此查询似乎会大幅放缓。

SELECT *, ( 3959 * acos( cos( radians(40.759105) ) * cos( radians( Latitude ) ) * cos( radians( longitude) - radians(-73.984654) ) + sin( radians(40.759105) ) * sin( radians( Latitude ) ) ) ) as distance FROM mcw_in WHERE Latitude <> '' ORDER BY distance LIMIT 0,20

如何在MySQL中创建索引以解决缓慢问题?还有其他解决方案 - 比如使用任何地理空间数据类型吗?

3 个答案:

答案 0 :(得分:2)

答案 1 :(得分:0)

但实际上这在MySQL中不起作用,因为它们还没有真正实现这些功能。

如果你对它开放,我建议使用PostGIS或Spatialiate(分别在Postgresql和SQLLite上运行)甚至是mongodb或geocouch。它们具有更大的实现空间功能套件。如果你看一下MySQL文档,它主要说空间函数“未实现”。

答案 2 :(得分:0)

最好通过定义围绕中心的边界框来使用范围查询。以下查询搜索离中心距离$ dist的最近20个位置($ lat0,$ lng0),结果按距离排序。你需要两个索引,一个在'lat',一个在'lng'。可以找到一些解释here

SELECT *,
    ( 6371 * acos(
    cos(radians($lat0)) * cos(radians(lat)) * cos(radians(lng) - radians($lng0)) +
    sin(radians($lat0)) * sin(radians(lat))
    ) ) AS distance
FROM `locations`
WHERE lat < degrees( asin( sin(radians($lat0)) * cos($dist / 6371) +
        cos(radians($lat0)) * sin($dist / 6371) * cos(radians(0)) ))
  AND lat > degrees( asin( sin(radians($lat0)) * cos($dist / 6371) +
        cos(radians($lat0)) * sin($dist / 6371) * cos(radians(180)) ))
  AND lng < $lng0 - degrees( atan2(sin(radians(90)) * sin(radians($dist / 6371)) * cos(radians($lat0)),
        cos(radians($dist / 6371)) - sin(radians($lat0)) * sin(radians($lat0))) )
  AND lng > $lng0 + degrees( atan2(sin(radians(90)) * sin(radians($dist / 6371)) * cos(radians($lat0)),
        cos(radians($dist / 6371)) - sin(radians($lat0)) * sin(radians($lat0))) )
ORDER BY distance LIMIT 20;