应用场景为已知某用户的地理位置,即经纬度,获取他附近的商家信息按距离远近排序

从mysql5.6.1以后开始支持 ST_Distance 函数用来计算对象的空间关系,并且支持地理参数类型为 Point和Point,或point和MultiPoint(不限制顺序)

从mysql8.0.18开始支持所有几何类型的地理SRS自变量的距离计算

而从mysql5.7.6以后新增加一个方法用来测球面上两点距离

ST_Distance_Sphere(g1, g2 [, radius]) radius指球体半径,缺省值为地球半径

SRS: 用来描述几何的定义空间被称为空间参照系

废话说了这么多直接上干货

例如:

沈丘县周口市中国466300
         "geometry" : {
            "location" : {
               "lat" : 33.4096812,
               "lng" : 115.0984158
            }

拱墅区杭州市中国310000
         "geometry" : {
            "location" : {
               "lat" : 30.2734437,
               "lng" : 120.155262
            }

计算两地之间的距离单位米

select ST_Distance_sphere(point(120.155262, 30.2734437), point(115.0984158, 33.4096812));

与工具测算的相差27米,误差也算可以接收,误差的原因猜测是半径取值问题,根据公式计算

select ST_Distance_sphere(point(0, 0), point(180, 0)) /pi(); 得出ST_Distance_sphere 函数的地球半径取值为 6370986 米

如果是从程序中处理也可以使用字符串的形式

select ST_Distance_sphere(PointFromText('point(120.155262 30.2734437)'),PointFromText('point(115.0984158 33.4096812)'));

注意:point坐标的第一个参数是经度(-180,180),第二个参数是维度(-90,90)实际此值是(-85.05112878,85.05112878),mysql中命令中point坐标用 逗号 分隔,字符串的point 用 空格 分隔

另外一点是关于经纬的存储精度问题

维基百科中精确到固定位数可辨识的程度表

经度取值范围为[0,180],纬度的取值范围为[0,90],一般情况下辨识度达到人 这一级别就可以,即6位小数,因此选择为

longitudes(经度): decimal(9,6)
latitudes (纬度): decimal(8,6)

经度应该比纬度是要多存一位。

另外如果需要达到专业的测量结果,可以选用最高精度:

longitudes(经度): decimal(11,8)
latitudes (纬度): decimal(10,8)

维基百科说明decimal就是用于存储地理位置信息的,所以选择 decimal 作为存储类型也是可以经得住推敲的;但实际情况使用decimal会比float字段查询耗费更多时间

经过1000万条的数据库对点(20.000006, 10.000005)获取某长度范围的数据耗时对比测试

select t.* from(
select id,lat,lng,ST_Distance_sphere(point(lng,lat), point(20.000006, 10.000005)) 'dis' from partner_store_song1000m
)t 
where t.dis < 1000
order by t.dis desc limit 10;

mysql字段类型 1公里内数据耗时 10公里内数据耗时 100公里内数据耗时
decimal(11,8) 7.9秒 7.9秒 8.3秒
float(11,8) 5.7秒 5.8秒 6秒

可以看出使用decimal字段会比float更耗时,而实际业务不要求很高的精度,所以选择float,这种字段在数据量为100万条数据时,获取100KM内的距离排序取10条只需要1秒左右时间

优化

在以上测试实际耗时还是令人很难接受,可以看出数据量越小则耗时越少,优化的思路是过滤掉不需要的数据后再进行运算排序

比如已知某点(20.000006, 10.000005) 获取其固定距离的最大最小经纬度,先对数据进行一次筛选,即lng = 20.000006, lat= 10.000005

$range = 180 / pi() / 6370986 * 1;     //最后1 就代表搜索 1m 之内
$lngR = $range / cos($lat * pi() / 180);
$maxLng = $lng + $lngR;//最大经度
$minLng = $lng - $lngR;//最小经度
$maxLat = $lat + $range;//最大纬度
$minLat = $lat - $range;//最小纬度

select t.* from(
select id,lat,lng,ST_Distance_sphere(point(lng,lat), point(20.000006, 10.000005)) 'dis' from partner_store_song1000
where
lng < 20.000006 + (180 / pi() / 6370986 * 10000 )/ cos(10.000005 * pi() / 180)
 and lng > 20.000006 - (180 / pi() / 6370986 * 10000 )/ cos(10.000005 * pi() / 180)
 and lat < 10.000005 + 180 / pi() / 6370986 * 10000
 and lat > 10.000005 - 180 / pi() / 6370986 * 10000
)t 
where t.dis < 10000
order by t.dis limit 10;

1000万条数据检索结果

mysql字段类型 1公里内数据耗时 10公里内数据耗时 100公里内数据耗时
float(11,8) 20豪秒 110豪秒 0.9秒

mysql 距离计算排序相关推荐

  1. mysql 下 计算 两点 经纬度 之间的距离 含具体sql语句

    mysql取字段逗号分隔的第一个 cover字段为:(admin/LUpiEMD1Pk6U6B,admin/LUpiEMD1Pk6U6B,admin/LUpiEMD1Pk6U6B) 取逗号分隔第一个词 ...

  2. mysql经纬度距离计算 按距离排序

    mysql距离计算,单位km/m,以及按照距离排序 方法一:计算出来的结果单位为m -- 纬度:31.182592 store_locy 经度:121.431744 store_locxSELECT ...

  3. oracle近似查找,距离内的Oracle空间搜索

    对于mySQL距离搜索,你有很好的参考. 忘记Oracle Spatial的东西.代码太多,复杂性太大,没有足够的增值. 这是一个可以解决问题的查询.这使用法定里程的距离.编辑这修复了mdarwin提 ...

  4. 根据经纬度,获取方圆10公里内的数据

    文章转载地址https://www.cnblogs.com/jiafuwei/p/5699091.html感谢作者. mysql距离计算,单位m,以及排序 lon 经度 lat 纬度 一般地图上显示的 ...

  5. 数学建模——多元分析、综合评价与决策

    一.多元分析 聚类分析 最短距离法+聚类图 [1]Q型聚类(样本) (1)样本之间 闵氏距离: 注意量纲要相同,避免多重相关性 马氏距离: 其中,是p维总体Z的协方差矩阵 不受量纲的影响 (2)聚类之 ...

  6. mysql计算两gps坐标的距离_mysql 计算两坐标间的距离

    mysql 5.6.1 加入了空间数据支持功能,新增了st_*相关函数,可以非常方便的计算两个地理坐标点的距离了. 如下例子:按我的坐标计算周边坐标的距离并由近到远排序 select name,st_ ...

  7. mysql 计算gps坐标距离_mysql、sqlserver和php计算GPS经纬度坐标距离

    摘要:mysql.sqlserver.oracle和php计算GPS经纬度坐标距离 mysql计算GPS经纬度距离DELIMITER $$ CREATEDEFINER=`root`@`localhos ...

  8. php 经纬度 距离排序,php mysql 根据经纬度计算距离和排序

    #1.两点距离(1.4142135623730951) select st_distance(point(0,0),point(1,1)); select st_distance(point (120 ...

  9. mysql 半径,MySQL基于距离半径的搜索和区域搜索POI实践

    因为应用是基于MySql的,所以我们的技术选型也是主要有两种:一种是多边形是否包含,一种是对每一个点进行计算. 首先看第一种:区域内搜索 在我们的业务平台中有很多景区的,每个景区都有围栏地址和中心点地 ...

最新文章

  1. 影响HP服务器的磁盘性能的重要因素 -- 阵列卡的缓存和电池
  2. NHibernate 错误
  3. 入门Qt——hello, world
  4. 30秒内便能学会的30个超实用Python代码片段
  5. JavaScript中赋值运算符的使用
  6. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析
  7. Vue生命周期通俗理解
  8. 设计素材 | 来一份秋高气爽——秋季促销海报
  9. Leetcode每日一题:181.employees-earning-more-than-their-managers(超过经理收入的员工)
  10. Android使用拖拽控件来布局界面并展示
  11. GB28181协议RTP传输
  12. UTM坐标和WGS84坐标转换
  13. 在线股票配资配资股票交易整站源码/牛股跟投带实盘策略区块链网站整站源码
  14. MCS-51系列单片机硬件结构
  15. oracle外部表kup-04023,kup-04040访问外部表时
  16. 智课雅思词汇---二十五、形容词后缀-ate-fic-ose-ulent-olent-ous-ulous-y
  17. 实现正负值及多条Y轴 Echarts柱状图
  18. Matlab解决脚本中中文乱码问题
  19. notepad编译java文件_notepad编译java
  20. 百度快速收录技巧总结

热门文章

  1. gitlab Enter passphrase for key
  2. 解决谷歌翻译不能使用的问题(2023.01.14)
  3. python爬虫概述
  4. 改掉几个坏习惯,养成几个习惯
  5. Altium 布线技巧
  6. 推荐四款非常好用的免费音乐播放器
  7. 面试自我介绍注意哪些
  8. 整理10类Java毕设练手项目,献给帅帅的计算计专业毕业人
  9. 等精度测频原理--频率计
  10. Linux机器rpm安装vsftpd