2016-11-15 19 views
1

私は特にMYSQLクエリについて知識がなく、それらを最適化していないので、私は少し助けが必要です。私は国際的な都市のテーブルをチェックして、テーブルの経度と緯度の値に基づいて最も近い10の都市を探します。この非常に遅いMySQLクエリの最適化

次のように私はこれを使用しているクエリである:

SELECT City as city, 
     SQRT(POW(69.1 * (Latitude - 51.5073509), 2) + 
      POW(69.1 * (-0.1277583 - Longitude) * COS(Latitude/57.3), 2)) AS distance 
from `cities` 
group by `City` 
having distance < 50 
order by `distance` asc 
limit 10 

(経度&緯度値は明らかに自分のコードに動的に配置されている)

時々これは約3-4 mintuesを取ることができます私の開発環境を完成させる。

私はここで古典的な間違いを犯しましたか、このデータを取得するためにはるかに良いクエリがありますか?

ご協力いただければ幸いです。 Cityを想定し

+0

実行計画を提供できますか? – Jester

+0

選択の計算は一般的に遅いので、私はあなたの問題だと思っています。 – Jester

+0

http://stackoverflow.com/a/38771805/267540およびhttp://stackoverflow.com/a/38548557/267540 – e4c5

答えて

0

はユニークであり、あなたは、GROUP BYを乱用し、Cityが一意である場合にはクリーンなコード

SELECT City as city, 
     SQRT(POW(69.1 * (Latitude - 51.5073509), 2) + 
      POW(69.1 * (-0.1277583 - Longitude) * COS(Latitude/57.3), 2)) AS distance 

from `cities` 

where SQRT(POW(69.1 * (Latitude - 51.5073509), 2) + 
      POW(69.1 * (-0.1277583 - Longitude) * COS(Latitude/57.3), 2)) < 50 

order by `distance` asc 

limit 10 

  • は、その後、凝集は単一の行で行われ得るために行っています。
    MySQLはsort操作を使用してGROUP BYを実装します。
    ソートの複雑さはO(n * log(n))なので、インデックスがなければGROUP BYの複雑さになります。
  • CityがHAVINGでのフィルタリングと一意でない場合は、OPが意図していない1つの任意の行に対してCLAUSEが実行されます。

有するケースとの両方のフィルタリングに関連するとHAVINGフィルタリングが凝集カラム上で行われる場合、パフォーマンス上の利点は、操作により若干重い計算及びグループが著しく低減存在である有し行数

select x,... from ... group by x having ... some heavy calculations on x ... 
+0

複雑な述語がwhere句で非効率的であると思われるかもしれません(そして、/ byによってグループ化された理由です)、おそらくあなたはその点について詳しく説明できますか? –

+0

@Used_By_すでに、編集された回答を参照 –

+0

@Used_By_既に、再編集されています –