地理位置geo处理之mysql函数
目前越来越多的业务都会基于LBS,附近的人,外卖位置,附近商家等等,现就讨论离我最近这一业务场景的解决方案。
原文:https://www.jianshu.com/p/455d0468f6d4
目前已知解决方案有:
- mysql 自定义函数计算
- mysql geo索引
- mongodb geo索引
- postgresql PostGis索引
- redis geo
- ElasticSearch
本文测试下mysql 函数运算的性能
准备工作
创建数据表
CREATE TABLE `driver` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`lng` float DEFAULT NULL,
`lat` float DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建测试数据
在创建数据之前先了解下基本的地理知识:
全球经纬度的取值范围为: 纬度-9090,经度-180180
中国的经纬度范围大约为: 纬度3.8653.55,经度73.66135.05
北京行政中心的纬度为39.92,经度为116.46
越北面的地方纬度数值越大,越东面的地方经度数值越大
度分转换: 将度分单位数据转换为度单位数据,公式:度=度+分/60
分秒转换: 将度分秒单位数据转换为度单位数据,公式:度 = 度 + 分 / 60 + 秒 / 60 / 60
在纬度相等的情况下:
- 经度每隔0.00001度,距离相差约1米
在经度相等的情况下:
- 纬度每隔0.00001度,距离相差约1.1米
mysql函数计算
DELIMITER //
CREATE DEFINER=`root`@`localhost` FUNCTION `getDistance`(
`lng1` float(10,7)
,
`lat1` float(10,7)
,
`lng2` float(10,7)
,
`lat2` float(10,7)
) RETURNS double
COMMENT '计算2坐标点距离'
BEGIN
declare d double;
declare radius int;
set radius = 6371000; #假设地球为正球形,直径为6371000米
set d = (2*ATAN2(SQRT(SIN((lat1-lat2)*PI()/180/2)
*SIN((lat1-lat2)*PI()/180/2)+
COS(lat2*PI()/180)*COS(lat1*PI()/180)
*SIN((lng1-lng2)*PI()/180/2)
*SIN((lng1-lng2)*PI()/180/2)),
SQRT(1-SIN((lat1-lat2)*PI()/180/2)
*SIN((lat1-lat2)*PI()/180/2)
+COS(lat2*PI()/180)*COS(lat1*PI()/180)
*SIN((lng1-lng2)*PI()/180/2)
*SIN((lng1-lng2)*PI()/180/2))))*radius;
return d;
END//
DELIMITER ;
创建数据python脚本
# coding=utf-8
from orator import DatabaseManager, Model
import logging
import random
import threading
""" 中国的经纬度范围 纬度3.86~53.55,经度73.66~135.05。大概0.00001度差距1米 """
# 创建 日志 对象
logger = logging.getLogger()
handler = logging.StreamHandler()
formatter = logging.Formatter(
'%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
# Connect to the database
config = {
'mysql': {
'driver': 'mysql',
'host': 'localhost',
'database': 'dbtest',
'user': 'root',
'password': '',
'prefix': ''
}
}
db = DatabaseManager(config)
Model.set_connection_resolver(db)
class Driver(Model):
__table__ = 'driver'
__timestamps__ = False
pass
def ins_driver(thread_name,nums):
logger.info('开启线程%s' % thread_name)
for _ in range(nums):
lng = '%.5f' % random.uniform(73.66, 135.05)
lat = '%.5f' % random.uniform(3.86, 53.55)
driver = Driver()
driver.lng = lng
driver.lat = lat
driver.save()
thread_nums = 10
for i in range(thread_nums):
t = threading.Thread(target=ins_driver, args=(i, 400000))
t.start()

以上脚本创建10个线程,10个线程插入4万条数据。耗费150.18s执行完,总共插入40万条数据
测试
- 测试环境
系统:mac os
内存:16G
cpu: intel core i5
硬盘: 500g 固态硬盘
测试下查找距离(134.38753,18.56734)这个坐标点最近的10个司机
select *,`getDistance`(134.38753,18.56734,`lng`,`lat`) as dis from driver ORDER BY dis limit 10
- 耗时:18.0s
- explain:全表扫描
我测试了从1万到10万间隔1万和从10万到90万每间隔10万测试的结果变化

结论
- 此方案在数据量达到3万条查询耗时就会超过1秒
- 大约每增加1万条就会增加0.4秒的耗时
作者:麦田348462402
链接:https://www.jianshu.com/p/455d0468f6d4
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
地理位置geo处理之mysql函数的更多相关文章
- Mysql - 函数
Mysql提供的函数是在是太多了, 很多我都见过, 别说用了. 园子里面, 有人弄了一个比较全的. MYSQL函数 我这里会将他写的完全拷贝下来, 中间会插入一些自己项目中使用过的心得 一.数学函数 ...
- mysql连接查询,封装mysql函数
连接查询 交叉连接语法: select * | 字段列表 from 表1 cross join 表2 内连接: select *|字段列表 from 左表 inner join 右表 on 左表. ...
- MySQL 函数大全
mysql函数大全 对于针对字符串位置的操作,第一个位置被标记为1. ASCII(str) 返回字符串str的最左面字符的ASCII代码值.如果str是空字符串,返回0.如果str是NULL,返回NU ...
- MySQL函数不能创建的解决方法
MySQL函数不能创建,是一个很麻烦的问题,下面就为您提供了一个解决此问题的方法,如果您也遇到过类似的问题,不妨一看. http://database.51cto.com/art/201010/229 ...
- Mysql函数:Last_insert_id()语法讲解
Mysql函数可以实现许多我们需要的功能,下面介绍的Mysql函数Last_insert_id()就是其中之一,希望对您学习Mysql函数能有所帮助. 自动返回最后一个INSERT或 UPDATE 查 ...
- linux下mysql函数的详细案列
MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *pas ...
- MySQL函数讲解(MySQL函数大全)
讲mysql函数之前先给大家展示一下利用mysql函数的一个例子: SELECT i.item_id, i.item_name, i.cid, i.last_update_time, u.url, u ...
- mysql函数全解析
本文摘自:http://www.cnblogs.com/cocos/archive/2011/05/06/2039469.html mysql函数大全 对于针对字符串位置的操作,第一个位置被标记为1. ...
- MySQL函数笔记
MySQL函数笔记 日期函数 SELECT t1.xcjyrq, t1.* FROM view_sbxx t1 WHERE t1.syzt ; SELECT t1.xcjyrq, t1.* FROM ...
随机推荐
- Nginx(六)-- 配置文件之Gzip
1.概念及作用 Gizp主要对内容.静态文件做压缩,用来提升网站访问速度,节省带宽. 2.使用方法 gzip既可以配置在server中,也可以配置在server外,此处配置在server中,如下: ...
- ConcurrentModificationException 详解
工作中碰到个ConcurrentModificationException.代码如下: List list = ...;for(Iterator iter = list.iterator(); ite ...
- Failure to transfer org.springframework.boot:spring-boot-starter-parent:pom:2.0.1.RELEASE from https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempt
第一次用 Spring Starter Project 创建一个Spring应用时,POM 文件报错: Project build error: Non-resolvable parent POM f ...
- Clock skewdetected. Your build may be incomplete.
解决方法: find . -type f | xargs -n touch make clean make
- Android——使用 Intent传递类
定义要传递的类事,必须加上 public class Movie implements Serializable { } 传入类: public void onItemClick(AdapterVie ...
- SNAT DNAT MASQUERADE 区别
SNAT,DNAT,MASQUERADE都是NATMASQUERADE是SNAT的一个特例SNAT是指在数据包从网卡发送出去的时候,把数据包中的源地址部分替换为指定的IP,这样,接收方就认为数据包的来 ...
- 【vue学习】vue中怎么引用laydate.js日期插件
此贴意在解决一个妹子的问题 https://q.cnblogs.com/q/101462 下载js包 http://www.layui.com/laydate/ 将laydate下载的包解压放入sta ...
- 【cs229-Lecture14】主成分分析法
本节课内容: 因子分析 ---因子分析中的EM步骤的推导过程 主成份分析:有效地降低维度的方法 因子分析 混合高斯模型的问题 接下来讨论因子分析模型,在介绍因子分析模型之前,先看高斯分布的另一种写法, ...
- python爬虫---->scrapy的使用(一)
这里我们介绍一下python的分布式爬虫框架scrapy的安装以及使用.平庸这东西犹如白衬衣上的污痕,一旦染上便永远洗不掉,无可挽回. scrapy的安装使用 我的电脑环境是win10,64位的.py ...
- swagger环境搭建
下面所用工具下载 http://editor.swagger.io/#/ demo 一.安装 swagger editor 说明:安装swagger前需要安装node工具 工具安装 ...