经纬度距离查询优化实例

 

最近参与开发一个SNS类型的社交程序,里面要记录用户的经纬度,还要按照某个已知位置查询附近的用户,这类应用在社交类产品里面算最常见的了,起初在网上搜索了一下,没找到同类文章,为了实现根据一个已知位置(double lon_me, double lat_me)查询double distance范围内的用户的功能,做了一个最简单的实现,那就是遍历所有lon,lat数据,在客户端计算距离,然后比较距离,这当然是最容易想到的实现方法了,第一版为了快速实现就是这么做的,后来又想了一个改进,把计算距离的公式放到mysql里面去,也许这样会快一点,再后面又想了一个改进,那就是根据已知位置(lon_me, lat_me)把distance范围的矩形求出来,然后先比较经纬度,只有在该矩形区域内的经纬度才有可能距离符合要求,当然如果不进一步精确验证就用一个小矩形在distance不大的情况下也是没啥问题的,即使要再进行距离计算那也是很小数据量的计算,计算量大幅度降低了,但到底速度能提高多少呢,我向另一个组的同事要来了50万条数据,分别用方法1,方法2,方法3进行了简单比较,统计如下:

方法

耗时(毫秒)

说明

方法一

约1650

遍历所有数据,到客户端用c++函数计算距离

方法二

约2315

将计算距离的公式作为mysql的内置公式

方法三

约15

先计算矩形,再在符合要求的结果集里面计算距离

以上测试数据都是在我本地的win7上完成的,mysql也跑在本地,测试的时候机器上还跑了一个虚拟机,我也没打算要测试出多精确的结果,只要大概的估算一下数量级即可。

测试前我原以为方法二可能会比方法一快,但实际上方法二还是比方法一慢很多,这么说来应该是c++函数的计算速度比mysql的内置函数快很多的原因。至于方法三,那是肯定要快很多了,因为这个方法将计算分成了两步,第一步求矩形,先通过简单的范围比较把可能符合要求的结果集合求出来,然后再求距离,这样就将复杂计算简化了很多,最终入围需要进行精确计算距离的数据很少,因此计算复杂度极大地降低了。不过需要说明的是,这个时候lat和lon都需要加索引,否则第一步求矩形的时候就需要遍历了,我特意去掉了这两个索引后测试了一下,这个时候耗时300多毫秒,可见这个索引的作用是巨大的。

需要特别说明的是我这个矩形范围的估算从逻辑上来说是不很严格的,不过对distance比较小的情况下误差不大,对SNS类型应用来说完全可接受,对大多数对距离要求不非常精确的应用来说也没啥问题,但如果要求非常严格的情况下,这样的估算可能是不符合精度要求的。

作为提速方案,其实还有更多可能的改进方法,如将数据全部加载到内存里面去,特别是把索引加载到内存里面去,速度还有进一步提升的空间,当然如果是用第三方缓存方案,将数据加载到内存里面的这个方法将碰到同步的问题,要维护内存数据和db数据的一致其实也是个麻烦的问题,最理想的是直接用内存数据库,这样具体应用的时候就可忽略同步问题,将同步问题完全交给内存数据库去做。

地理信息系统发展到今天,有的数据库已经有对经纬度数据的一系列优化处理方案,不过我也只是知道有而没有深入用过他们,更不了解他们的原理和效率,欢迎熟悉的朋友提供数据并欢迎和我交流。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值