[备忘]mysql中计算地图上两点距离
最近有个lbs相关的项目,要求向用户位置推荐周边的(DB中的)已有地标。数据取自GPS的坐标系经纬度。是个典型求两点距离最优解的命题。
(需求接近于“滴滴拉屎”,自行脑洞一下)
备选的实现方向有:
- 使用地图服务商(例如百度地图、腾讯地图)提供的测距API计算 —— 缺点:不适合进行大量的计算,依赖第三方API业务稳定性有不可控,有网络请求延迟;
- 在后端脚本中进行计算 —— 缺点:每次查询需要取出数据库中全部地标数据,还需要自行实现排序结构化计算结果
- 在数据库中进行计算排序 —— 缺点:加重DB负担
衡量利弊后,似乎#3是比较理想的方案,于是找到了以下这个
《mysql 下 计算 两点 经纬度 之间的距离》
https://www.cnblogs.com/u0mo5/p/4260382.html
算法如下
round(6378.138*2*asin(sqrt(pow(sin( (`lat1`*pi()/180-`lat2`*pi()/180)/2),2)+cos(`lat1`*pi()/180)*cos(`lat2`*pi()/180)* pow(sin( (`lon1`*pi()/180-`lon2`*pi()/180)/2),2)))*1000)
验证的demo
#113.348407,22.968607 //lat, lon
#113.333603,22.973731 //地图距离1.6km
SELECT round(6378.138*2*asin(sqrt(pow(sin( (113.348407*pi()/180-113.333603*pi()/180)/2),2)+cos(113.348407*pi()/180)*cos(113.333603*pi()/180)* pow(sin( (22.968607*pi()/180-22.973731*pi()/180)/2),2)))*1000) as dist_m
dist_m
1663
经过验证计算结果和地图上直接测距一致, 单位 米
补充
初期的地标库比较小只有一百多条,所以直接用上面的sql便可以满足。若今后地标数据扩大,也会面临计算量大mysql计算负荷重的问题(需要计算后再排序,索引对提升速度无效)。届时进行的优化措施可以把坐标点按经纬度划分成若干间距的网格,仅在用户坐标的网格内(或加上周边一共9个网格内)进行检索,可以有效缩减计算量。
毕竟,如果我在北京王府井人有三急,我知道阿姆斯特丹有豪华六星厕所也没意义(笑)
