我正在构建一个在线Symfony应用程序,作为开发过程的一部分,我的任务是根据与登录用户的距离对大量数据库记录进行排序。用户可以随意扩大搜索范围,达到整个世界的大小。
我随时可以访问已登录用户的GPS坐标,在数据库表格中我保存了各种兴趣点的纬度和经度。
目前,POI表中只有400条记录,但由于每当我访问它时必须提取的数据量,查询时间已经略微超过一秒。向此类工作负载添加400个三角函数很快就会使执行时间超出可接受范围。
因此,我需要一种快速准确计算这种距离的方法;
我已经阅读了多篇暗示Haversine公式的文章,但我发现这对我的需求来说太慢了,甚至像this那样的广泛文章都没有任何帮助;
考虑到我可以很快接触到数以千计的POI,同时有来自世界各地的数千名用户被登录,我怎么能接近(并希望解决)这样的问题呢?
我使用的是PHP 7.0,Symfony 3.2和Doctrine; pdo连接到Mysql服务器,使用innoDB作为数据库引擎
我的客户价值准确超过速度,但不能等待超过5秒
查询结果被分页,因此将分类委托给客户是不可能的
数据库和php服务器共享相同(可怕)的资源池,这样的池将与其他应用程序共享
在旁注中,某些POI可能会在某个日期之后到期
答案 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)
只会使其更具“人性”可读性。
希望它可以帮到你!