使用空间点类型在 MySQL 中存储 Lat Lng 值
Posted
技术标签:
【中文标题】使用空间点类型在 MySQL 中存储 Lat Lng 值【英文标题】:Storing Lat Lng values in MySQL using Spatial Point Type 【发布时间】:2011-06-27 02:18:11 【问题描述】:我只是为我正在编写的网站设计一个新数据库。我正在寻找现在存储 Lat 和 Lng 值的最佳方式。
过去我一直使用 DECIMAL 并在表单中使用 PHP/MySQL 选择:
SQRT(POW(69.1 * (fld_lat - ( $lat )), 2) + POW(69.1 * (($lon) - fld_lon) * COS(fld_lat / 57.3 ), 2 )) AS distance
寻找最近的匹配地点。
开始阅读有关新技术的更多信息,我想知道是否应该使用 Spatial Extensions。 http://dev.mysql.com/doc/refman/5.1/en/geometry-property-functions.html
不过,实际信息非常少,并且对如何存储数据存在疑问。我现在不使用 DECIMAL,而是使用 POINT 作为数据类型吗?
此外,一旦存储为 POINT,是否可以轻松地从中获取 Lat Lng 值,以防我想在地图上绘制它,或者我是否应该另外将 lat lngs 再次存储为 DECIMALS?
我知道我应该使用 PostGIS,因为这里的大多数帖子都说我只是不想学习新的数据库!
跟进
我一直在玩新的 POINT 类型。我已经能够使用以下方法添加 Lat Lng 值:
INSERT INTO spatialTable (placeName, geoPoint) VALUES( "London School of Economics", GeomFromText( 'POINT(51.514 -0.1167)' ));
然后我可以使用以下方法从 Db 中获取 Lat 和 Lng 值:
SELECT X(geoPoint), Y(geoPoint) FROM spatialTable;
这一切看起来都不错,但是距离的计算是我需要解决的问题。显然 MySQL 有一个用于距离函数的占位符,但暂时不会发布。在一些帖子中,我发现我需要执行以下操作,但是我认为我的代码有点错误:
SELECT
placeName,
ROUND(GLength(
LineStringFromWKB(
LineString(
geoPoint,
GeomFromText('POINT(52.5177, -0.0968)')
)
)
))
AS distance
FROM spatialTable
ORDER BY distance ASC;
在本例中,geoPoint 是使用上述 INSERT 输入数据库的 POINT。
GeomFromText('POINT(52.5177, -0.0968)'
是我要计算距离的 Lat Lng 值。
更多跟进
相当愚蠢,我只是在没有真正考虑的情况下放入了 SQL 的 ROUND 部分。把它拿出来给我:
SELECT
placeName,
(GLength(
LineStringFromWKB(
LineString(
geoPoint,
GeomFromText('POINT(51.5177 -0.0968)')
)
)
))
AS distance
FROM spatialTable
ORDER BY distance ASC
这似乎给了我所需的正确距离。
我想目前唯一需要回答的问题是,我是否只是通过现在使用 Spatial 让自己过上困难,还是让自己适应未来……
【问题讨论】:
未来证明:You Aren't Gonna Need It 非常有用的信息。 不,你确实需要它。如果您想使用 MySQL 并(快速)搜索某个点附近的地方,则需要空间索引。 距离是用哪个单位计算的? 是的,距离是用什么单位计算的? 【参考方案1】:我认为您应该始终使用易于获得的***别抽象。如果您的数据是地理空间数据,则使用地理空间对象。
但要小心。 Mysql 是最糟糕的地理空间数据库。它可以用于点,但它的所有多边形功能都完全被破坏了 - 他们将多边形更改为其边界矩形,然后对此进行回答。
让我印象最深的例子是,如果你有一个代表日本的多边形并且你问日本有哪些地方,符拉迪沃斯托克就会进入列表!
Oracle 和 PostGIS 没有这个问题。我希望 MSSQL 不会,任何使用 JTS 作为其引擎的 Java 数据库都不会。地理空间好。 MySQL 地理空间错误。
请阅读此处How do you use MySQL spatial queries to find all records in X radius?,它已在 5.6.1 中修复。
万岁!
【讨论】:
事情已经改变。当一个我们的 MBR 函数依赖于计算minimum bounding rectangle
时,会发生 mysql 错误的多查询。从 mysql 5.6 开始。新功能出现了。以“st_*”开头的函数执行得更好。例如contains(g1, g2)
与st_contains(g1, g2)
。更多信息请访问percona.com/blog/2013/10/21/…
是的,我认为 OpenGIS 决定 st_ 名称在数据库供应商之间更具可移植性。绝对应该使用它们。不过,我认为它们在 5.6 中并不准确。
请注意,在 `5.6.23-72.1 - Percona Server (GPL)` 上, st_contains 似乎按预期工作。仅针对附近(即:最多 800 公里距离)坐标进行测试。也许对于长距离坐标它的表现不同
搜索更深入***.com/questions/7782873/… 说 5.6.1 符合您的经验。【参考方案2】:
Mysql GIS 雅格尼:
如果您没有使用 GIS 的经验,那么学习空间扩展实际上就像学习一个新数据库,再加上一点数学知识和许多首字母缩略词。地图,投影,srids,格式......你是否必须学习所有这些来计算给定纬度/经度的点之间的距离:可能不是,你会整合第 3 方 GIS 数据还是使用比点更复杂的东西,什么您将使用坐标系吗?
回到 yagni:做尽可能简单的事情,在这种情况下,用 php 或使用简单的 SQL 实现您的代码。一旦您遇到障碍并决定您需要空间,请阅读 GIS 系统、坐标系、项目和约定。
到那时,您可能会想要 PostGIS。
【讨论】:
【参考方案3】:这是一件好事,因为这样您就可以在查询中使用空间索引。限制为边界框,例如,限制要比较的行数。
【讨论】:
【参考方案4】:如果您可以在后端添加一些额外的代码,请使用 Geohash。
它以前缀表示更广泛区域的方式将坐标编码为字符串。字符串越长,精度越高。
它具有多种语言的绑定。
http://en.wikipedia.org/wiki/Geohash https://www.elastic.co/guide/en/elasticsearch/guide/current/geohashes.html
【讨论】:
以上是关于使用空间点类型在 MySQL 中存储 Lat Lng 值的主要内容,如果未能解决你的问题,请参考以下文章
使用 R 将 lat/long 点的数据框空间连接到多边形 shapefil