我有一个拥有4万个场地的数据库,现在正在增长。
假设我是红点
我希望能够尽快找到最接近的记录。
然而,下一个项目的距离也可能是任何东西。并且也可能有0-n匹配。但是,当我只是寻找1时,我是否需要加载所有40000结果?
如何按距离对记录进行排序?它应该在MYSQL还是PHP中完成? 这种计算几乎发生在每个用户,每页的每个请求上,因此解决方案需要快速。
编辑感谢快速而有前途的答案,我需要查看这些资源,并在几天内接受/评论答案。
答案 0 :(得分:8)
这个Scribd演示文稿中包含了这个问题(理论+数学公式+ Mysql): Geo Distance with MySQL
我希望它涵盖你需要的一切
答案 1 :(得分:3)
最简单的解决方案是简单地计算每条记录的距离并按此值排序。问题是:这非常昂贵且您不能使用索引。您可以通过仅查看记录的子集来降低成本,可能会受到边界框的限制,如此处的海报所示。
如果您想要一个清晰而快速的解决方案,请查看MySQL的 Spatial Extensions 。这些完全是为了你想做的。这些支持:
This howto提供了一些示例:
CREATE TABLE address (
address CHAR(80) NOT NULL,
address_loc POINT NOT NULL,
PRIMARY KEY(address),
SPATIAL KEY(address_loc)
);
CREATE TABLE cab (
cab_id INT AUTO_INCREMENT NOT NULL,
cab_driver CHAR(80) NOT NULL,
cab_loc POINT NOT NULL,
PRIMARY KEY(cab_id),
SPATIAL KEY(cab_loc)
);
SELECT
c.cab_driver,
ROUND(GLength(LineStringFromWKB(LineString(AsBinary(c.cab_loc),
AsBinary(a.address_loc)))))
AS distance
FROM cab c, address a
WHERE a.address = 'Foobar street 110'
ORDER BY distance ASC LIMIT 1;
答案 2 :(得分:1)
创建一个“边界框”以在SQL查询的WHERE子句中使用,如本article on Movable Type中所述(使用PHP代码示例),然后在查询中包含Haversine公式以计算实际距离,以及按距离ASC排序结果。最近的场地将是结果集中的第一个回归。
这是帮助您提高性能的边界框,因为这意味着您只需对数据的一小部分进行昂贵的距离计算
如果初始查询未返回任何记录,请加宽边界框,然后再次执行查询,直到获得响应为止。
答案 3 :(得分:1)
除了通过反复试验之外,找不到距离是没有效的方法。也就是说,使用MySQL,您无法按目标距离对记录进行排名,然后选择最顶层的记录。最好的方法是选择您认为最接近的记录将在其中的距离。太大的数字,你会得到太多的记录,太小的数字,你不会得到任何。假设你选择40个单位。
WHERE xcoord BETWEEN n - 40 AND n + 40 AND ycoord BETWEEN n - 40 AND n + 40
现在你已经在80 x 80的盒子里面得到了所有的坐标记录,以你的目标为中心(如果你在纬度和经度上工作,那个盒子会有点倾斜,但那不是'真的很重要)。现在使用Haversine方程式(如果你正在处理纬度和经度)或者毕达哥拉斯(Pythagoras)(如果它只是笛卡尔坐标)来计算目标与每个点之间的距离。