java - 查找到所选点特定距离内的所有地址的最佳方法是什么

标签 java mysql spring hibernate latitude-longitude

我正在开发一个应用程序,该应用程序应该显示某个位置特定距离内的地址。我知道如何找到两点之间的距离,但问题是我不确定在性能方面什么是最好的方法。

一种方法是检索所有地址并在后端对所选地址逐一检查,但有没有办法最大限度地减少我从数据库中检索的项目数量,而不是使用内存?最好的方法是什么?如何做?

假设我有 300,000 条记录,我必须全部检索它们并计算它们到所选点的距离吗?正如James建议的那样,我可以拥有不同区域的记录并计算距离,那么通过查询或Java计算距离,哪种方法比较好?

  public class Address{
    long Id;
    Double latitude;
    Double longitude;
    ..
  }

Calculation

public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
  double earthRadius = 3958.75;
  double dLat = Math.toRadians(lat2-lat1);
  double dLng = Math.toRadians(lng2-lng1);
  double sindLat = Math.sin(dLat / 2);
  double sindLng = Math.sin(dLng / 2);
  double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
        * Math.cos(Math.toRadians(lat1)) *     Math.cos(Math.toRadians(lat2));
  double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  double dist = earthRadius * c;

  return dist;
}

This questionthis one提供通过mysql计算距离的方法,但是Java或mysql哪种方式更好我很困惑。

最佳答案

当我在 MySQL 中实现这一点时(用于在扁球体上存储位置,这基本上就是地球(我假设你说的是地球!)),我已将尽可能多的预先计算的信息存储在数据库。因此,对于存储 latitude 的行和 longitude ,我还在插入时计算以下字段:

  • radiansLongitude ( Math.toRadians(longitude) )
  • sinRadiansLatitude ( Math.sin(Math.toRadians(latitude) )
  • cosRadiansLatitude ( Math.cos(Math.toRadians(latitude) )

然后,当我搜索 latitude 的 X 个单位内的地方时/longitude有问题的是,我准备的声明如下:

from Location l where
    acos(
        sin(:latitude) * sinRadiansLatitude + 
        cos(:latitude) * cosRadiansLatitude * 
        cos(radiansLongitude - :longitude) 
        ) * YYYY < :distance
    and l.latitude>:minimumSearchLatitude
    and l.latitude<:maximumSearchLatitude 
    and l.longitude>:minimumSearchLongitude 
    and l.longitude<:maximumSearchLongitude 
    order by acos(
                sin(:latitude) * sinRadiansLatitude + 
                cos(:latitude) * cosRadiansLatitude * 
                cos(radiansLongitude - :longitude)  
        ) * YYYY asc

在哪里 YYYY = 3965 为您提供以英里为单位的距离或 YYYY = 6367 可用于以公里为单位的距离。

最后,我使用了maximumSearchLatitude/maximumSearchLongitude/minimumSearchLongitude/maximumSearchLongitude在数据库必须执行任何计算之前从结果集中排除大部分点的参数。你可能需要也可能不需要这个。如果您确实使用它,则取决于您为这些参数选择什么值,因为这取决于您要搜索的内容。

显然需要在数据库中明智地应用索引。

使用这种方法的好处是永远不会改变但每次都需要的信息只计算一次,而计算 radiansLongitude 的值, sinRadiansLatitude , cosRadiansLatitude每次执行搜索时的每一行都会很快变得非常昂贵。

另一个选项是使用 geospatial index ,这意味着所有这些都由数据库为您处理。不过,我不知道 Hibernate 与它的集成程度如何。

免责声明:很久没看这个了,我不是 GIS 专家!

关于java - 查找到所选点特定距离内的所有地址的最佳方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28847954/

相关文章:

java - 使用 Spring 5 下载 PDF 文件时出错

java - 中断tomcat线程是否安全

java - 如果我的项目没有模块但仍想在 GAE 中的后端实例上运行(使用 Java),如何执行长时间运行的任务?

java - 将多个表映射到单个实体

Mysql Sum 或 Group_concat 基于不同的 id

mysql - 在删除级联时使用外键删除多个条目

java - 从 ListableBeanFactory 获取类型和泛型的 bean

mysql - 优化mysql表避免锁

Spring外层事务失败回滚内层事务

spring - Postgres 和 Spring Data JPA : operator does not exist: bytea = bigint