我看过有的童鞋是这样处理的,在sql里直接打算间隔,然后排序,大概因此下的写法:
ACOS( SIN((#{lat} 3.1415) / 180 ) SIN((merchant.latitude 3.1415) / 180 ) + COS((#{lat} 3.1415) / 180 ) COS((merchant.latitude 3.1415) / 180 ) COS((#{lng} 3.1415) / 180 - (merchant.longitude 3.1415) / 180 ) ) 6380 AS distance
这种写法一看就欠妥,在sql中繁芜运算是不推举的。这个需求可以优化下筛选周遭指定例模内的商家然后在内存中进行打算间隔排序,无需在数据库中全部打算一遍间隔然后排序。如果以用户为中央,筛选周遭一公里范围的商家然后按间隔排序,打算出前后1公里范围的经纬度差值,大概如下图
简化成这个模型后,黑点地方的数据是不须要的,但是这部分数据可以忽略不计,稍后在内存中计算间隔可以去除。我们知道地球可以算作是一个圆球

地球周长是263713.14 那么1公里对应的经度差值是(1/(263713.14))180 大概0.004498, 1公里对应的纬度差值(1/(263713.14))90 大概0.002249,以是在sql中筛选between lng-0.004498 and lng+0.004498 纬度同样如此。
不过有人帮我们处理好了这些事情,只须要引入jar包即可
<dependency> <groupId>com.spatial4j</groupId> <artifactId>spatial4j</artifactId> <version>0.5</version></dependency>int radius = 1; //筛选范围 公里//lon, lat用户当前的经纬度SpatialContext geo = SpatialContext.GEO;Rectangle rectangle = geo.getDistCalc().calcBoxByDistFromPt( geo.makePoint(lon, lat), radius DistanceUtils.KM_TO_DEG, geo, null);rectangle.getMinX() getMaxX() getMinY() getMaxY()既是表示周遭1公里内的经纬度。这样数据中的筛选条件就可以优化下了
这样效率就能提高了很多,筛选出数据之后,还须要打算详细的间隔然后排序,打算间隔如下
SpatialContext geo = SpatialContext.GEO;double distance = geo.calcDistance(geo.makePoint(lon, lat), geo.makePoint(memberLon, memberLat)) DistanceUtils.DEG_TO_KM;
当然这只是初步优化方案,如果你有更好的方案欢迎不才方留言。