PHPMySQL中的地理搜索(距离)(性能)

PHPMySQL中的地理搜索(距离)(性能),第1张

PHP / MySQL中的地理搜索(距离)(性能)

计算边界框以选择SQL查询的WHERe子句中的行的子集,以便仅对该行子集执行昂贵的距离计算,而不是对表中的全部200k记录执行。本文在Movable
Type
(带有PHP代码示例)中描述了该方法。然后,您可以针对该子集在查询中包含Haversine计算,以计算实际距离,并在该点处将其包含在HAVINg子句中。

这是帮助您提高性能的边界框,因为这意味着您仅对一小部分数据进行了昂贵的距离计算。实际上,这是与Patrick所建议的方法相同的方法,但是Movable
Type链接对方法进行了详尽的解释,以及可用于构建边界框和SQL查询的PHP代码。

编辑

如果您认为Haversine不够准确,那么还有Vincenty公式。

//  Vincenty formula to calculate great circle distance between 2 locations expressed as Lat/Long in KMfunction VincentyDistance($lat1,$lat2,$lon1,$lon2){    $a = 6378137 - 21 * sin($lat1);    $b = 6356752.3142;    $f = 1/298.257223563;    $p1_lat = $lat1/57.29577951;    $p2_lat = $lat2/57.29577951;    $p1_lon = $lon1/57.29577951;    $p2_lon = $lon2/57.29577951;    $L = $p2_lon - $p1_lon;    $U1 = atan((1-$f) * tan($p1_lat));    $U2 = atan((1-$f) * tan($p2_lat));    $sinU1 = sin($U1);    $cosU1 = cos($U1);    $sinU2 = sin($U2);    $cosU2 = cos($U2);    $lambda = $L;    $lambdaP = 2*M_PI;    $iterLimit = 20;    while(abs($lambda-$lambdaP) > 1e-12 && $iterLimit>0) {        $sinLambda = sin($lambda);        $cosLambda = cos($lambda);        $sinSigma = sqrt(($cosU2*$sinLambda) * ($cosU2*$sinLambda) + ($cosU1*$sinU2-$sinU1*$cosU2*$cosLambda) * ($cosU1*$sinU2-$sinU1*$cosU2*$cosLambda));        //if ($sinSigma==0){return 0;}  // co-incident points        $cosSigma = $sinU1*$sinU2 + $cosU1*$cosU2*$cosLambda;        $sigma = atan2($sinSigma, $cosSigma);        $alpha = asin($cosU1 * $cosU2 * $sinLambda / $sinSigma);        $cosSqAlpha = cos($alpha) * cos($alpha);        $cos2SigmaM = $cosSigma - 2*$sinU1*$sinU2/$cosSqAlpha;        $C = $f/16*$cosSqAlpha*(4+$f*(4-3*$cosSqAlpha));        $lambdaP = $lambda;        $lambda = $L + (1-$C) * $f * sin($alpha) * ($sigma + $C*$sinSigma*($cos2SigmaM+$C*$cosSigma*(-1+2*$cos2SigmaM*$cos2SigmaM)));    }    $uSq = $cosSqAlpha*($a*$a-$b*$b)/($b*$b);    $A = 1 + $uSq/16384*(4096+$uSq*(-768+$uSq*(320-175*$uSq)));    $B = $uSq/1024 * (256+$uSq*(-128+$uSq*(74-47*$uSq)));    $deltaSigma = $B*$sinSigma*($cos2SigmaM+$B/4*($cosSigma*(-1+2*$cos2SigmaM*$cos2SigmaM)- $B/6*$cos2SigmaM*(-3+4*$sinSigma*$sinSigma)*(-3+4*$cos2SigmaM*$cos2SigmaM)));    $s = $b*$A*($sigma-$deltaSigma);    return $s/1000;}echo VincentyDistance($lat1,$lat2,$lon1,$lon2);


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5052832.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-15
下一篇 2022-11-15

发表评论

登录后才能评论

评论列表(0条)

保存