PHP,Mysql-根据一个给定经纬度的点,进行附近地点查询–合理利用算法,效率提高2125倍...

目前的工作是需要对用户的一些数据进行分析,每个用户都有若干条记录,每条记录中有用户的一个位置,是用经度和纬度表示的。
还有一个给定的数据库,存储的是一些已知地点以及他们的经纬度,内有43W多条的数据。
现在需要拿用户的经纬度和已知地点进行距离匹配,如果它们之间的距离小于一定的数据,比如说500米,就认为用户是在这个地点。
MYSQL本身是支持空间索引的,但是在5.x的版本中,取消了对Distance()和Related()的支持,参考这里:MySQL 5.1参考手册 :: 19. 中的空间扩展 19.5.6. 测试几何类之间空间关系的函数, 无法使用空间的距离函数去直接去查询距离在一定范围内的点。所以,我首先想到的是,对每条记录,去进行遍历,跟数据库中的每一个点进行距离计算,当距离小 于500米时,认为匹配。这样做确实能够得到结果,但是效率极其低下,因为每条记录都要去循环匹配40W条数据,其消耗的时间可想而知。经过记录,发现每 条记录处理的时间消耗达到1700ms,针对每天上亿的数据量,这样一个处理速度,让人情何以堪啊。。。
我自己也有个想法,就是找到每条记录所在点的经纬度周围的一个大概范围,比方说正方形的四个点,然后使用mysql的空间计算,使用MBR去得出点在这个矩形内的已知记录,然后进行匹配。可惜,自己没想出能计算到四个点经纬度的方法。
意外的,查询到了一个关于这个计算附近地点搜索初探,里面使用python实现了这个想法。
所以参考了一下原文中的算法,使用PHP进行了实现。
实现原理也是很相似的,先算出该点周围的矩形的四个点,然后使用经纬度去直接匹配数据库中的记录。

红色部分为要求的搜索范围,绿色部分我们能间接得到的结果范围

红色部分为要求的搜索范围,绿色部分我们能间接得到的结果范围

 

参考wiki百科上的一些球面计算公式:

  • Great-circle distance
  • Haversine formula

假设已知点的经纬度分别为$lng, $lat
先实现经度范围的查询,
在haversin公式中令φ1 = φ2,可得:

用PHP进行计算,就是:

Example
1
2
3
//$lat 已知点的纬度
$dlng =  2 * asin(sin($distance / (2 * EARTH_RADIUS)) / cos(deg2rad($lat)));
$dlng = rad2deg($dlng);//转换弧度

然后是纬度范围的查询,
在haversin公式中令 Δλ = 0,可得

在PHP中进行计算,就是:

Example
1
2
$dlat = $distance/EARTH_RADIUS;//EARTH_RADIUS地球半径
$dlat = rad2deg($dlat);//转换弧度

最后,就可以得出四个点的坐标:
left-top : (lat + dlat, lng – dlng)
right-top : (lat + dlat, lng + dlng)
left-bottom : (lat – dlat, lng – dlng)
right-bottom: (lat – dlat, lng + dlng)

我把以上方法写成了一个函数,综合起来就是:

Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
define(EARTH_RADIUS, 6371);//地球半径,平均半径为6371km
 /**
 *计算某个经纬度的周围某段距离的正方形的四个点
 *
 *@param lng float 经度
 *@param lat float 纬度
 *@param distance float 该点所在圆的半径,该圆与此正方形内切,默认值为0.5千米
 *@return array 正方形的四个点的经纬度坐标
 */
 function returnSquarePoint($lng, $lat,$distance = 0.5){
    $dlng =  2 * asin(sin($distance / (2 * EARTH_RADIUS)) / cos(deg2rad($lat)));
    $dlng = rad2deg($dlng);
     
    $dlat = $distance/EARTH_RADIUS;
    $dlat = rad2deg($dlat);
     
    return array(
                'left-top'=>array('lat'=>$lat + $dlat,'lng'=>$lng-$dlng),
                'right-top'=>array('lat'=>$lat + $dlat, 'lng'=>$lng + $dlng),
                'left-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng - $dlng),
                'right-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng + $dlng)
                );
 }
//使用此函数计算得到结果后,带入sql查询。
$squares = returnSquarePoint($lng, $lat);
$info_sql = "select id,locateinfo,lat,lng from `lbs_info` where lat<>0 and lat>{$squares['right-bottom']['lat']} and lat<{$squares['left-top']['lat']} and lng>{$squares['left-top']['lng']} and lng<{$squares['right-bottom']['lng']} ";

在lat和lng上建立一个联合索引后,使用此项查询,每条记录的查询消耗平均为0.8毫秒,相比以前的1700ms,真的是天壤之别啊。效率真真的是以前的2125倍~~

总结:这应该也不是效率最好的办法,但是效率比以前确实有明显的提升。请记住,总有办法更好的。

原文链接:http://digdeeply.org/archives/06152067.html

转载于:https://www.cnblogs.com/longhao/p/4071275.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/472844.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js固定表格行列_纯前端表格控件SpreadJS V14.0发布:组件化编辑器+数据透视表

SpreadJS 是一款基于 HTML5 的纯前端表格控件&#xff0c;兼容 450 种以上的 Excel 公式&#xff0c;具备“高性能、跨平台、与 Excel 高度兼容”的产品特性&#xff0c;可为用户提供高度类似 Excel 的功能&#xff0c;满足 Web Excel组件开发、 表格文档协同编辑、 数据填报、…

天池 在线编程 区间统计(队列)

文章目录1. 题目2. 解题1. 题目 给定一个01数组 arr 和 一个整数 k, 统计有多少区间符合如下条件: 区间的两个端点都为 0 (允许区间长度为1)区间内 1 的个数不多于 k arr 的大小不超过 10^5 样例 1: 输入: arr [0, 0, 1, 0, 1, 1, 0], k 1 输出: 7 解释: [0, 0], [1, 1],…

android 模糊查询控件_第三十二篇:在SOUI2.0中像android一样使用资源

SOUI2.0之前&#xff0c;在SOUI中使用资源通常是直接使用这个资源的name(一个字符串)来引用。使用字符串的好处在于字符串能够表达这个资源的意义&#xff0c;因此使用字符串也是现代UI引擎常用的方式。尽管直接使用字符串有意义明确的优点&#xff0c;它同样也有缺点&#xff…

采用java信号量(semaphore)让线程轮流打印

semaphore是java.util.concurrent包下的并发工具类。 A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially relea…

天池 在线编程 有序队列

文章目录1. 题目2. 解题1. 题目 给出了一个由小写字母组成的字符串 S。 然后&#xff0c;我们可以进行任意次数的移动。 在每次移动中&#xff0c;我们选择前 K 个字母中的一个&#xff08;从左侧开始&#xff09;&#xff0c;将其从原位置移除&#xff0c;并放置在字符串的末…

网站搜索功能怎么实现_电商网站上的搜索功能是如何实现的?

今天是刘小爱自学Java的第159天。感谢你的观看&#xff0c;谢谢你。学习计划安排如下&#xff1a;索引库本质上和数据库类似&#xff0c;也是存储数据的&#xff0c;既然如此自然也会有增删改查。那么这个索引库到底有何特别应用呢&#xff1f;索引库的特别之处在于它的查询&am…

android蓝牙通信_Flutter通过BasicMessageChannel实现Flutter 与Android iOS 的双向通信

题记&#xff1a;——不到最后时刻&#xff0c;千万别轻言放弃&#xff0c;无论结局成功与否&#xff0c;只要你拼博过&#xff0c;尽力过&#xff0c;一切问心无愧。通过 Flutter 来进行移动应用开发&#xff0c;打包 Android 、iOS 双平台应用程序&#xff0c;在调用如相机、…

apache mysql php 安装配置_Windows下Apache,MySql,PHP安装配置

本文目标在Windows8.1 x64下 全手工安装Apache、PHP、MySQL&#xff0c;使用NetBeans调试第一个Hello,World!程序。安装Apache打开http://httpd.apache.org 左侧Download!点From a Mirror&#xff0c;看到当前最新稳定版本未2.4.12&#xff0c; 看到现在Windows的版本已经不像以…

MapReduce既是编程模型又是计算框架

learn from 从0开始学大数据&#xff08;极客时间&#xff09; MapReduce 编程模型 包含 Map 和 Reduce 两个过程 map 的主要输入是一对 <Key, Value> 值&#xff0c;输出一对 <Key, Value> 值将相同 Key 合并&#xff0c;形成 <Key, Value 集合 >再将这个…

python设置单元格宽度_Python xlwt-访问现有单元格内容,自动调整列宽

我刚刚实现了一个包装类&#xff0c;它跟踪输入项的宽度。看起来效果不错。import arial10 class FitSheetWrapper(object): """Try to fit columns to max size of any entry. To use, wrap this around a worksheet returned from the workbooks add_sheet me…

java mysql 流媒体_red5-rtmp-push

red5-rtmp-push介绍获取视频流 进行人脸识别后推送到red5服务器(人脸识别技术由虹软提供)整个系统共有两个项目组成启用说明1.主要是借用ifast框架,主要的服务类就一个,其他的都是多余的。2.首先修改 resources/application-dev.yml 中的 red5.url : rtmp://red5ip/oflaDemo/ 改…

工单更改历史记录(轉載)

一、自定义表结构 二、生产工单出口增强 三、查询报表 一、自定义表结构 表ZPCO02 MANDT MANDT CLNT 3 0 客户端 AUFNR AUFNR CHAR 12 0 订单号 MATNR MATNR CHAR 18 0 物料号 FILED FIELDNAME CHAR 30 0 字段名 AENAM AENAM CHAR 12 0 对象更改人员的名称 LAEDA LAEDA DATS 8 …

MapReduce 计算框架如何运作

learn from 从0开始学大数据&#xff08;极客时间&#xff09; 1. MapReduce 作业启动和运行机制 作业涉及三类关键进程&#xff1a; 大数据应用进程 这类进程是启动 MapReduce 程序的主入口&#xff0c;主要是指定 Map 和 Reduce 类、输入输出文件路径等&#xff0c;并提交作业…

python能做机器人吗_python深度学习 人工智能是做机器人吗?

我们经常听到”Python“与”人工智能“这两个词&#xff0c; 也很容易混淆这两个词&#xff0c; 那么Python和人工智能到底什么关系呢&#xff1f; Python人工智能工程师待遇怎么样&#xff1f; 通过这篇文章详细解答一下&#xff1a; 关于Python Python是一门计算机程序语言&a…

linux忘记mysql密码_Linux下忘记Mysql密码的找回方法(图)

Mysql隔一段时间不访问&#xff0c;也许你会忘记访问密码&#xff0c;这时该怎么办&#xff0c;重装mysql吗&#xff1f;这个代价也太大了&#xff0c;我们这里介绍两种恢复密码的方法。方法一&#xff1a;因为Mysql密码存储于数据库mysql中的user表中&#xff0c;所以我们只要…

单元测试的7种境界

1. 以各种借口拒绝单元测试Unit Test&#xff0c;比较常用的是“你没有足够的时间(进行单元测试)”。  无论是对单元测试的老手还是新手编写单元测试还是有一定得工作量的&#xff0c;而且单元测试也需要掌握大量的测试框架和工具(光一个junit或testng你很难工作地很happy)。…

Yarn 资源调度框架

learn from 从0开始学大数据&#xff08;极客时间&#xff09; Hadoop 主要是由三部分组成&#xff1a; 分布式文件系统 HDFS分布式计算框架 MapReduce分布式集群资源调度框架 Yarn Yarn 的架构

python连接sql数据库_python连接SQL数据库

前言 上次通过学习&#xff0c;懂得了如何通过不同的对象来定位页面的元素&#xff08;id,class_name,tag_name,xpath,css等&#xff09;&#xff0c;可以实现模拟点击的功能。当然&#xff0c;这只是初期的web自动化的一点小成绩。当你觉得这些都应用的差不多的情况下&#xf…

mysql mtop 使用_MYSQLMTOP监控环境搭建

MySQLMTOP是一个由PythonPHP开发的MySQL企业级监控系统。系统由Python实现多进程数据采集和告警&#xff0c;PHP实现WEB展示和管理。最重要是MySQL服务器无需安装任何Agent&#xff0c;只需在监控WEB界面配置相关数据库信息功能非常强大&#xff1a;可对上百台MySQL数据库的状态…

javascript正则表达式入门

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head><title> RegExp对象</title><script>/*function validation(obj){//1.得到文本框的值//var …