Bagaimanakah saya boleh mengoptimumkan pertanyaan carian geo dalam PHP/MySQL untuk carian berasaskan jarak pada set data yang besar?

DDD
Lepaskan: 2024-11-13 09:42:02
asal
217 orang telah melayarinya

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

Pengoptimuman Geo-Search (Jarak) dalam PHP/MySQL

Apabila melakukan pertanyaan berasaskan jarak pada jadual besar yang mengandungi pasangan latitud-longitud, mengoptimumkan prestasi pertanyaan menjadi penting. Pertimbangkan cabaran berikut yang dihadapi oleh pertanyaan MySQL:

  • MySQL berulang melalui semua baris, menimbulkan kos pengiraan yang tinggi.
  • Pelanjutan geospatial seperti R-Trees mungkin rumit dan memerlukan kepakaran matematik.

Terikat Carian Kawasan

Penyelesaian yang cekap adalah dengan menentukan kotak sempadan di sekitar kawasan yang diminati. Pertanyaan kemudiannya boleh memilih baris dalam kawasan sempadan ini, mengurangkan bilangan pengiraan jarak dengan ketara. Artikel Movable Type menyediakan panduan terperinci tentang membina kotak sempadan dan menggunakannya dalam pertanyaan SQL.

Formula Vincenty untuk Hasil Lebih Tepat

Jika formula Haversine tidak mencukupi untuk ketepatan, formula Vincenty boleh digunakan. Contoh JavaScript ini menunjukkan pelaksanaannya untuk mengira jarak bulatan besar:

//  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);
Salin selepas log masuk

Kesimpulan

Dengan memanfaatkan kotak sempadan dan mempertimbangkan kaedah pengiraan jarak alternatif, anda boleh meningkatkan dengan ketara prestasi pertanyaan geo-carian anda pada MySQL. Sama ada carian berskala besar atau komponen kritikal aplikasi web anda, pengoptimuman ini akan meningkatkan pengalaman pengguna dan memastikan operasi pangkalan data yang cekap.

Atas ialah kandungan terperinci Bagaimanakah saya boleh mengoptimumkan pertanyaan carian geo dalam PHP/MySQL untuk carian berasaskan jarak pada set data yang besar?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan