【问题标题】:Methods for geographic distance search in MySQLMySQL中地理距离搜索的方法
【发布时间】:2015-01-08 08:49:31
【问题描述】:

我正在寻找一种快速的方法来搜索距另一个给定点一定距离内的点。我有一个 MyISAM 表,其中点空间索引表示地理位置(纬度、经度)。

如果 MySQL 支持它,我认为 ST_DWithin 会完成这项工作。但事实并非如此,所以我得到了以下表达式,它使用缓冲区生成一个圆圈,然后查找落在这个圆圈内的点:

ST_Within(geopoint, ST_Buffer(Point(@lat, @lng), @radius))

它似乎工作正常,我相信它使用索引。但这是一个足够好的解决方案吗?出于地理目的,ST_Within 和 ST_Buffer 的精确度如何?

更新: 我的结论是 MySQL 不提供对地理坐标的支持,并且所有操作都在欧几里得平面上完成(即使您指定了 SRID)。根据位置的不同,这最终会导致很大的不精确性。所以在使用 MySQL Spatial 函数之前需要对坐标进行转换。

【问题讨论】:

  • 如果您正在做很多空间/地理方面的工作,从长远来看升级到 Postgres/PostGIS 可能是一个更好的选择(而不是每次发现缺少的功能时都创建一个解决方法)。跨度>

标签: mysql gis mysql-5.6


【解决方案1】:

我们在工作中会做类似的事情。

我们每小时收到大约 100 万次查询,当我们使用空间索引时,它基本上会关闭数据库并且查询会进入挂起状态。一些查询等待大约8,000 秒(大约2 小时)。所以我们必须找到另一种方法,这是我们能想到的最好的方法,它现在不再备份数据库,并以毫秒为单位返回结果。

我们要做的是首先我们有一个距离函数,如下所示:

CREATE FUNCTION `distance`(`lat1` DECIMAL(10,7), `lon1` DECIMAL(10,7), `lat2` DECIMAL(10,7), `lon2` DECIMAL(10,7)) RETURNS double
BEGIN
    DECLARE X DOUBLE;
    DECLARE PI DECIMAL(21, 20);
    SET PI = 3.14159265358979323846;
    SET X  = SIN(lat1 * PI / 180)
    * SIN(lat2 * PI / 180)
    + COS(lat1 * PI / 180)
    * COS(lat2 * PI / 180)
    * COS((lon2 * PI / 180) - (lon1 * PI / 180));
    SET X = ATAN((SQRT( 1- POWER( X, 2))) / X);
    RETURN (1.852 * 60.0 * ((X / PI) * 180)) / 1.609344;
END

删除返回线上的/ 1.609344以获取公里数

然后我们有一个程序来计算您所在位置与周围区域之间的距离。从我们测试的结果来看,这是最快的(我们所拥有的简化版本):

CREATE PROCEDURE `MyRadius`(IN `p_lat` DOUBLE, IN `p_long` DOUBLE, IN `radius` INT)
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
    SELECT distance(p_lat, p_long, g.latitude, g.longitude) as distance, country, region, city
    from geocity g
    having distance <= radius
    order by distance asc limit 100;
END

您可能想要更改order 子句,因为我不确定您要如何订购它。

【讨论】:

  • 你的方法的问题是它没有利用索引,所以在大型数据库上它可能真的很慢!
  • 我们的数据库使用 3 个表,每个表中至少有 1,000,000 条记录,并且确实利用了索引。我们在latitudelongitude 上有一个索引
猜你喜欢
  • 2011-08-26
  • 2012-09-11
  • 2012-07-18
  • 2012-12-12
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 2012-03-06
  • 1970-01-01
相关资源
最近更新 更多