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:
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);
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!