计算大型数据集的地理点之间的距离

时间:2017-07-31 15:28:40

标签: php mysql symfony geographic-distance

我正在构建一个在线Symfony应用程序,作为开发过程的一部分,我的任务是根据与登录用户的距离对大量数据库记录进行排序。用户可以随意扩大搜索范围,达到整个世界的大小。

我随时可以访问已登录用户的GPS坐标,在数据库表格中我保存了各种兴趣点的纬度和经度。

目前,POI表中只有400条记录,但由于每当我访问它时必须提取的数据量,查询时间已经略微超过一秒。向此类工作负载添加400个三角函数很快就会使执行时间超出可接受范围。

因此,我需要一种快速准确计算这种距离的方法;

我已经阅读了多篇暗示Haversine公式的文章,但我发现这对我的需求来说太慢了,甚至像this那样的广泛文章都没有任何帮助;

考虑到我可以很快接触到数以千计的POI,同时有来自世界各地的数千名用户被登录,我怎么能接近(并希望解决)这样的问题呢?

我使用的是PHP 7.0,Symfony 3.2和Doctrine; pdo连接到Mysql服务器,使用innoDB作为数据库引擎
我的客户价值准确超过速度,但不能等待超过5秒
查询结果被分页,因此将分类委托给客户是不可能的 数据库和php服务器共享相同(可怕)的资源池,这样的池将与其他应用程序共享

在旁注中,某些POI可能会在某个日期之后到期

1 个答案:

答案 0 :(得分:0)

你让我添加它,所以我会。

你确定性能受到了来自Haversine的影响吗?我们在我的工作中成功地使用了这个公式的PHP实现大约2年,我们进行了大量的搜索(在高峰时间每分钟大约150k)。

我无法详细了解我的工作,但我可以说我们使用了sphinx,mongoDB,mysql和RabbitMq的组合。

在任何情况下,sphinx和mysql都会在100英里距离的距离计算中失去约2英里的距离计算能力差(这就是我们使用它的原因)

您可以做的一件事是对运行Haversine公式所需的时间进行基准测试,良好的基准测试是您遇到性能问题时的第一步。

虽然我不是交响乐用户,但我确实有一个专为此事做的课程。它是我在业余时间(Evolution)构建的更大框架的一部分。你可以在这里上课

https://github.com/ArtisticPhoenix/Evo/blob/master/Evo/Benchmark.php

使用起来非常简单

$mark = Benchmark::getInstance()->mark();

... code to time ...

echo Benchmark::getInstance()->format($mark);

并输出类似

的内容
10 milliseconds
5 minutes 3 milliseconds
ect..

它的设计使您可以使用多个marks

$mark = Benchmark::getInstance()->mark();

... code to time ...

$mark1 = Benchmark::getInstance()->mark();

 ... more code to time ...

echo "TotalTime: ".Benchmark::getInstance()->format($mark);
echo "MethodTime: ".Benchmark::getInstance()->format($mark1);

etc..

它基本上只是在您调用microtime(true)时记录mark()(true为浮点数)并返回标识符$mark然后如果您使用标识符调用mark($mark)它将会从当前microtime(true)中减去该值。调用format($mark)只会使其更具“人性”可读性。

希望它可以帮到你!