带有位置数据的大型 MySQL 数据库(21MM 记录) - 每个位置都有经纬度 - 需要运行“附近”查询
Posted
技术标签:
【中文标题】带有位置数据的大型 MySQL 数据库(21MM 记录) - 每个位置都有经纬度 - 需要运行“附近”查询【英文标题】:Large MySQL DB (21MM records) with location data - each location has lat and long - need to run 'nearby' query 【发布时间】:2011-07-29 02:33:26 【问题描述】:我们有一个大型位置数据库 - 为每一行指定了 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 中创建索引来解决缓慢的问题?有没有其他解决方案——比如使用任何地理空间数据类型?
【问题讨论】:
【参考方案1】:MySQL Manual :: Introduction to MySQL Spatial Support
MySQL Manual :: Creating Spatial Indexes
【讨论】:
【参考方案2】:但实际上这在 MySQL 中是行不通的,因为它们还没有真正实现这些功能。
如果您愿意,我会推荐使用 PostGIS 或 Spatialiate(分别在 Postgresql 和 SQLLite 上运行)甚至 mongodb 或 geocouch。它们具有更大的一套已实现的空间功能。如果您查看 MySQL 文档,它大多说空间函数“未实现”。
【讨论】:
【参考方案3】:最好通过定义围绕中心的边界框来使用范围查询。以下查询搜索距中心 ($lat0, $lng0) 距离 $dist 内最近的 20 个位置,结果按距离排序。您需要两个索引,一个在“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;
【讨论】:
以上是关于带有位置数据的大型 MySQL 数据库(21MM 记录) - 每个位置都有经纬度 - 需要运行“附近”查询的主要内容,如果未能解决你的问题,请参考以下文章
mysql 查询一年的数据 要按每个月20号统计 如何做 一条语句
导入大型数据库 - CPanel & MySQL & PHPMyAdmin
如何将大型 MySQL 数据库从一台服务器迁移到另一台服务器?