MySQL 地理空间查询 - 返回最近的行

标签 mysql sql geospatial database-performance

我有一个具有以下结构的表:

id | code | coordinates

ID 是主键,代码是我们内部应用程序使用的东西,坐标列是数据类型。

我需要构建一个查询,以快速将最近的行返回到一组坐标。

例如,如果我给出坐标 50.8,-1.3,我希望查询尽可能快地返回最近的行(或者至少比我下面的尝试更快)。

这是我的尝试。我会使用它,但它需要 0.5 秒才能返回结果。

SELECT localities.code
  FROM (
    SELECT glength(LineStringFromWKB( 
            LineString( 
            GeomFromText(astext(coordinates)), 
            GeomFromText(astext( PointFromWKB(POINT(663.422238,10.398996)))))))
      AS distance, code  
FROM locality
) localities
ORDER BY localities.distance ASC
LIMIT 1

任何人都可以利用地理空间扩展构建一个比这更快返回结果的查询吗?

最佳答案

首先,您在选择距离的表达式中有一点冗余。

我相信你可以使用

glength(LineString(coordinates,POINT(663.422238,10.398996))) AS distance

而不是你所拥有的。这可能对性能有一点帮助,但帮助不大。

构造的查询对您的 locality 表执行全表扫描以计算每个距离。然后它按距离对结果排序并返回第一个。

如果您对所讨论的几何形状没有任何先验知识,那么很难做得更好。但是,如果您可以在样本点周围放置一个边界框并将搜索限制在边界框内,那么您可以使用 SPATIAL 索引来大大加快速度。

要使用 SPATIAL 索引,您需要在表上使用 MyISAM 访问方法(InnoDB 将不起作用)。然后在您的 coordinates 列上创建索引。

然后你需要计算出合适的边界框。假设您要排除与候选 POINT(663.422238,10.398996) 距离超过 50 的任何点。

你需要做的是:

首先,创建一个几何对象,它是一条穿过边界框的对角线,如下所示:

GeomFromText(
   CONCAT('LINESTRING(',
          663.422238 - 50,' ', 10.398996 - 50, ',',
          663.422238 + 50,' ', 10.398996 + 50, ')'))

然后在这样的查询中使用具有空间索引利用函数 MBRContains()(最小边界矩形包含)的几何对象。

SELECT localities.code
  FROM (
     SELECT glength(LineString(coordinates,POINT(663.422238,10.398996))) AS distance,
            code 
       FROM locality
      WHERE  MBRContains(
                GeomFromText(
                       CONCAT('LINESTRING(',
                               663.422238 - 50,' ', 10.398996 - 50, ',',
                               663.422238 + 50,' ', 10.398996 + 50, ')')),
                coordinates )
       ) AS localities
ORDER BY localities.distance ASC
LIMIT 1

关键是边界框。这种运行查询的方式通过使用空间索引来选择表中希望考虑的非常小的行子集来节省时间。

我在这里为纬度/经度工作写了一些细节。 http://www.plumislandmedia.net/mysql/using-mysqls-geospatial-extension-location-finder/

请注意,有时要正确获取 GeomFromText 内容的语法有点麻烦。我希望它是对的,但我可能放错了逗号或其他东西。

关于MySQL 地理空间查询 - 返回最近的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24173014/

相关文章:

sql - 如何授予 Select 访问权限以在架构中查看

python - 如何使用 python 获取 eumetsat 图像像素的纬度和经度?

Mysql日期从字符串中选择

javascript - Bookshelf.js/Knex.js 太 "helpful"与 UTC DATETIME 列

mysql - 将数据插入数据库的最有效方法?准备好的语句、批量加载或多个插入语句?

php - 在数据库中存储应用程序权限

sql - 有效地获得铁路类别中最便宜的产品

php - 根据日期在不同的表中显示数据

javascript - 创建椭圆包络数据的 D3 映射

php - 使用 Php 查询 SQL 并为 GeoPolygon 输出 geojson