>  기사  >  데이터 베이스  >  대규모 데이터세트에 대한 거리 기반 검색을 위해 PHP/MySQL에서 지역 검색 쿼리를 어떻게 최적화할 수 있나요?

대규모 데이터세트에 대한 거리 기반 검색을 위해 PHP/MySQL에서 지역 검색 쿼리를 어떻게 최적화할 수 있나요?

DDD
DDD원래의
2024-11-13 09:42:02218검색

How can I optimize geo-search queries in PHP/MySQL for distance-based searches on large datasets?

PHP/MySQL의 지리 검색(거리) 최적화

위도-경도 쌍이 포함된 대규모 테이블에서 거리 기반 쿼리를 수행할 때, 쿼리 성능을 최적화하는 것이 중요해졌습니다. MySQL 쿼리가 직면한 다음 과제를 고려하십시오.

  • MySQL은 모든 행을 반복하므로 높은 계산 비용이 발생합니다.
  • R-Trees와 같은 지리공간 확장은 복잡할 수 있으며 수학적 전문 지식이 필요할 수 있습니다.

검색의 경계 영역

효율적인 솔루션은 관심 영역 주위에 경계 상자를 정의하는 것입니다. 그런 다음 쿼리는 이 경계 영역 내의 행을 선택하여 거리 계산 횟수를 크게 줄일 수 있습니다. Movable Type 기사는 경계 상자를 작성하고 이를 SQL 쿼리에 사용하는 방법에 대한 자세한 지침을 제공합니다.

보다 정확한 결과를 위한 Vincenty Formula

Haversine 공식이 충분하지 않은 경우 정확도가 높으면 Vincenty 공식을 배포할 수 있습니다. 이 JavaScript 예는 대원 거리 계산 구현을 보여줍니다.

//  Vincenty formula to calculate great circle distance between 2 locations expressed as Lat/Long in KM

function 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);

결론

경계 상자를 활용하고 대체 거리 계산 방법을 고려하면 크게 개선할 수 있습니다. MySQL에서의 지역 검색 쿼리 성능. 대규모 검색이든 웹 애플리케이션의 중요한 구성 요소이든 이러한 최적화는 사용자 경험을 향상시키고 효율적인 데이터베이스 운영을 보장합니다.

위 내용은 대규모 데이터세트에 대한 거리 기반 검색을 위해 PHP/MySQL에서 지역 검색 쿼리를 어떻게 최적화할 수 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.