2017-04-03 4 views
0

私は趣味のプロジェクトとして、会社のウェブサイトを作り始めました。私はウェブサイトのための複雑なコードを作成することはあまり進んでいないが、私はそれを試してみたかった。mysqlでHaversine数式を高速化するには?

オランダの郵便番号データベースが471000件以上あります。私はhaversineの式を使って、どの郵便番号が半径13キロ以内かを調べ、この結果に郵便番号を持つデータベースからすべてのユーザーを選択します。しかし、すべての結果をロードするには6秒かかります。このプロセスをどのようにスピードアップできますか?以下

コード:

$finder = $mysqli->query("SELECT lat, lng FROM postcodetabel WHERE postcode = '$s' OR plaats = '$s'"); 
$finder1 = mysqli_fetch_assoc($finder); 
$latitude = $finder1['lat']; 
$longitude = $finder1['lng']; 
$query = $mysqli->query("SELECT postcode, (
     6371 * acos (
     cos (radians('$latitude')) 
     * cos(radians(lat)) 
     * cos(radians(lng) - radians('$longitude')) 
     + sin (radians('$latitude')) 
     * sin(radians(lat)) 
    ) 
) AS distance 
FROM postcodetabel 
HAVING distance < 12 
ORDER BY distance ASC"); 

$quertie = $mysqli->query("SELECT bigav, id, naam, email, bedrijfsnaam, telnummer FROM gebruikers WHERE postcode = '$postcode' AND status = 1 AND soort LIKE '%" . $soort . "%'"); 
while($quertie2 = mysqli_fetch_assoc($quertie)) { echo ' 
<div class="kapper"> 
    <div class="kapperfoto"><img src="/vluggeknipt/ondernemer/pagina/uploads/'.$quertie2['bigav'].'" style="width:100px;height:100px;"></div> 
    <div class="boektekst"> 
     <font class="headingkap"><strong><a href="?page=profiel&id='.$quertie2['id'].'">Naar profiel &raquo;</a></strong></font><br/> 
    </div> 
    <div class="kappertext"> 
     <font class="headingkap"><a href="?page=profiel&id='.$quertie2['id'].'"><strong>'.$quertie2['naam'].'</strong></a></font><br/> 
     <i class="mobhide">'.$quertie2['email'].' - '.$quertie2['telnummer'].'</i><br/> 
     <i class="mobhide">'.$quertie2['bedrijfsnaam'].'</i> 
    </div></div><br/> 

    '; } 

事前に感謝します!

答えて

0

なぜあなたはクエリが集計関数を使用しないため、どこで(ただしどこでコードをリピートする必要がないのか)、そして完全な評価を行った結果を改善するためのスキャン

$query = $mysqli->query("SELECT postcode, (
     6371 * acos (
     cos (radians('$latitude')) 
     * cos(radians(lat)) 
     * cos(radians(lng) - radians('$longitude')) 
     + sin (radians('$latitude')) 
     * sin(radians(lat)) 
    ) 
) AS distance 
    FROM postcodetabel 
    WHERE 6371 * acos (
     cos (radians('$latitude')) 
     * cos(radians(lat)) 
     * cos(radians(lng) - radians('$longitude')) 
     + sin (radians('$latitude')) 
     * sin(radians(lat)))< 12 
    ORDER BY distance ASC"); 
3

このクエリは特に高速になることはありません。しかし、それを改善する方法はいくつかあります。

最初に:ここでは、ハウバーシン式は必要ありません。それが適用される補正は、地球の曲率が重要な要素である場合、または極の近くにある場合にのみ必要です。これらはどちらもここには該当しません。正確に計算する必要がある最大の距離は、水平線上ではほとんどない12マイルです。この規模では、地球は事実上平らなので、ピタゴラス定理は距離を計算するのに十分です。

緯度の1度は約69マイル、そして(オランダがどこにあるの周りに)52°Nで、経度の度がcos(52°) x 69 = 42.5マイルであるので、式は次のようになる。

sqrt(pow(69*(lat - $latitude), 2) + pow(42.5*(lng - $longitude), 2)) 

セカンド:緯度と経度の「はさみ試験」を使うことができます。あなたの目標地点からどの地点でも12マイル以上離れていれば、その地点の12マイル圏内にはいられません。この事実を利用して、距離計算を完全にスキップして、緯度と経度を高速に比較することができます。

WHERE (lat BETWEEN ($latitude - 12/69.0) AND ($latitude + 12/69.0)) 
    AND (lng BETWEEN ($longitude - 12/42.5) AND ($longitude + 12/42.5)) 

これは、完全な距離のチェックを置き換えていないことに注意してください!正しい半径の範囲内にない可能性のあるポイントをすばやくスローするのは、単に最初のステップです。インデックスがlatまたはlngの場合、データベースサーバーはデータベースの多くの行を調べないようにします。

+0

偉大な答え!この方法が合理的に正確である距離の上限を示すことができますか?言って、正解の5%以内? – richplane

関連する問題