【问题标题】:PHP calculate lan/lon distance performancePHP计算lan/lon距离性能
【发布时间】:2014-04-02 18:15:19
【问题描述】:

我的距离计算脚本存在严重的性能问题。

我在一个数据库中有大约 3000 个位置(这最终会增加一倍)。数据库结构相当复杂(类别、子类别)但带有 time();我看到这些查询并没有花费太多时间。

我有一个用户的纬度和经度 $_GET,我使用这个计算来确定该位置是否在某个半径范围内:

   function distance($lat1, $lon1, $lat2, $lon2, $unit) {

      $theta = $lon1 - $lon2;
      $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
      $dist = acos($dist);
      $dist = rad2deg($dist);
      $miles = $dist * 60 * 1.1515;
      $unit = strtoupper($unit);

      if ($unit == "K") {
        return ($miles * 1.609344);
      } else if ($unit == "N") {
          return ($miles * 0.8684);
        } else {
            return $miles;
          }
    }

// some sql queries to get the lat/lon from the locations

if ((distance($_GET["lat"], $_GET["long"], $row3["content"], $row4["content"], "K") . "") < 10) {

            //push to multidimensional array



        }

$row3["content"] 和 $row4["content"] 是纬度和经度值。对于 3000 个位置,此计算最多需要 13 秒!

我读到这个: Fastest Way to Find Distance Between Two Lat/Long Points

我认为基于纬度和经度的 $_GET 绘制一个框的选项可能已经删除了当前的计算。在 sql 查询中,我已经可以过滤掉 10 公里范围之外的位置。

但我有两个问题:

  1. 如果我将 SQL 更改为以下内容:... WHERE LAT >= x1 AND
  2. 作者在解释中谈到了“单位”。我一直在玩 lat/lon 值,但我如何实际计算 x1、x2、y1、y2,其中 $_GET 值是距离为 10 公里的中心点?

谢谢。

【问题讨论】:

  • 如果您对性能很认真,您应该考虑一些 GIS/空间解决方案。
  • 我确定问题与您的数据库代码有关,而不是计算两个坐标之间的距离。我不知道如何帮助您解决您的问题,因为您没有向我们展示这些问题。
  • 要显示的代码很多,但基本上是这样的: select * from table A - while mysqli_fetch_assoc select reference id's from table B (match with id's from table A) - while mysqli_fetch_assoc select LAT from table C(与表 B 中的参考 id 匹配)-而 mysqli_fetch_assoc 从表 C 中选择 LON(与表 B 中的参考 id 匹配)-而 mysqli_fetch_assoc { //距离计算 }
  • 这就是为什么大多数人会为他们的 SQL 查询生成一个边界框,以减少他们需要计算距离的记录数量:它并没有消除计算距离的需要,因为你是通过计算进一步减少数字,但它减少了您需要执行计算的次数
  • 谢谢,我已经更新了我的答案。我确实发现这是一种非常有效的方法,我能够将加载时间从 13 秒减少到只有 1 秒,这仅仅是因为在 SQl 查询中使用了边界框。

标签: php mysql latitude-longitude


【解决方案1】:

我能够将计算时间从 13 秒减少到 1 秒!

我通过使用 mysql 过滤掉不在我的纬度/经度坐标的 10 公里边界框内的位置来做到这一点。

我使用了这个代码:

  $rad = 10;  // radius of bounding circle in kilometers

  $R = 6371;  // earth's mean radius, km

  // first-cut bounding box (in degrees)
  $maxLat = $_GET['lat'] + rad2deg($rad/$R);
  $minLat = $_GET['lat'] - rad2deg($rad/$R);
  // compensate for degrees longitude getting smaller with increasing latitude
  $maxLon = $_GET['long'] + rad2deg($rad/$R/cos(deg2rad($_GET['lat'])));
  $minLon = $_GET['long'] - rad2deg($rad/$R/cos(deg2rad($_GET['lat'])));

我把我的mysql改成了这个:

$sql2 = "SELECT ....WHERE LAT BETWEEN '".$minLat."' AND '".$maxLat."'";
$sql3 = "SELECT ....WHERE LON BETWEEN '".$minLon."' AND '".$maxLon."'";

我的其余代码和计算完全相同,但不是进行 3000 次计算,而是 mysql 扫除了大部分。

我不知道这种方法在数学上是否 100% 正确,但据我所知,只要对我的初始编码稍作改动,它就可以运行得非常快,所以对于我的项目来说,它很棒。

当然还有来源:http://www.movable-type.co.uk/scripts/latlong-db.html

【讨论】:

    猜你喜欢
    • 2012-04-04
    • 1970-01-01
    • 2013-01-26
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    相关资源
    最近更新 更多