什么是在半径内查找大表的最快方法MySQL(纬度经度)

目前我有几个100k +行的表。 我正在试图查找如下的数据。

SELECT *, SQRT(POW(69.1 * (latitude - '49.1044302'), 2) + POW(69.1 * ('-122.801094' - longitude) * COS(latitude / 57.3), 2)) AS distance FROM stops HAVING distance < 5 ORDER BY distance limit 100 

但是目前这种方法在高负载下变慢。 有些查询需要20多秒才能完成。

如果有人知道任何更好的方法来优化这将是伟大的。

那么首先,如果你有很多的地理空间数据,你应该使用mysql的地理空间扩展,而不是像这样的计算。 然后,您可以创build空间索引 ,这将加快许多查询,而不必像上面那样写出长时间的查询。

使用与ST_Distance的比较或创build一个感兴趣的半径几何与ST_within可能会给你很好的结果,可能会比现在快很多。 然而,最好的和最快的方法来实现这一点, ST_Dwithin尚未在MySQL中实现。

空间索引绝对取决于MySQL版本。 我们的网站也search经纬度,但我们正在使用旧版本的MySQL(5.1-something)(没有空间索引)。 您的查询与我们的查询类似,但是我们的查询是基于弧度的。 根据你的具体需求,你可以优化它(从你有什么)相当多。

  1. 从数据库查询中绝对删除sqrt(),它必须为每一行计算 – 只有在显示到用户的实际距离时才计算它 – 也将“有距离<5”和“<25” 。 Sqrt是昂贵的,很容易移动到不需要计算的地方。
  2. 取消纬度/经度'49 .1044302',所以它是一个整数,并在查询外进行纬度/经度types检查。 这不会加快速度,但会防止由于lat / lonvariables中伪随机空白造成的不正确的转换。
  3. 将5转换为在每个方向上+/- 5的实际经度/纬度差,以产生一个限制范围(一个框)。 将它添加到查询的“where”部分 – 这个限制会让你得到一个大大减less,几乎精确的结果行集合 – 基本上,经纬度上的x和y +/-范围是结果的上限 – 计算出的对angular线只会使结果和它们的距离稍微变差。
  4. 在select之外移动一些数字,在那里 – 它将不得不扫描整个表格,并创build一个临时的表格,并在每一行上计算,以给出结果。 查询中的很多math可以转换为常量。
  5. 通过将纬度/经度(复制)的分辨率降低到另一个字段(也许乘以10或100并转换为INT)并在该字段上添加一个索引来加速行减less(select框)使用该字段与+/-在其中的界限,至less可以使用一个键 – mysql可以减less和更快的结果。

至less我们是这样做的。