地理位置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 ...
随机推荐
- Python 扩展知识
Python 练习题 Python 编程习惯 Python 转义字符 Python 格式化输出 Python 列表表达式 Python 生成器表达式 Python 序列化 Python2 与 Pyth ...
- 为啥RESTFULL如此重要?
为啥RESTFULL如此重要? 2014-6-3 20:13| 发布者: admin| 查看: 57| 评论: 0|来自: java365 摘要: 本文我们将讨论REST,它定义了一组体系架构原则,您 ...
- Google TensorFlow 机器学习框架介绍和使用
TensorFlow是什么? TensorFlow是Google开源的第二代用于数字计算(numerical computation)的软件库.它是基于数据流图的处理框架,图中的节点表示数学运算(ma ...
- input回车问题
今天有一个问题,就是input对象没有加任何事件自己回车导致跳到了404页面.处理的时候,并发现没找到回车事件的控制. 那么只有一种情况,就是自带的回车控制. 百度了一下,如下面博文里面的写法.我这边 ...
- 基于ThinkPHP3.23的简单ajax登陆案例
本文将给小伙伴们做一个基于ThinkPHP3.2.的简单ajax登陆demo.闲话不多说.直接进入正文吧. 可能有些小伙伴认为TP自带的跳转页面挺好,但是站在网站安全的角度来说,我们不应该让会员看到任 ...
- 《转》Python学习(13)-Python的字符编码
转自 http://www.cnblogs.com/BeginMan/p/3166363.html 一.字符编码中ASCII.Unicode和UTF-8的区别 点击阅读:http://www.cnbl ...
- IOS设计模式第八篇之键值观察模式
版权声明:原创作品,谢绝转载!否则将追究法律责任. 键值观察模式: 在KVO,一个对象可以要求被通知当他的某个特殊的属性被改变了.自己或者另一个对象.如果你感兴趣你可以阅读更多的信息参考: Apple ...
- 【框架学习】Nancy 框架
Nancy 框架 http://liulixiang1988.github.io/nancy-webkuang-jia.html .是一个轻量级用于构建http相应的web框架: .与mvc类似,有自 ...
- 云计算设计模式(二十一)——Sharding分片模式
云计算设计模式(二十一)——Sharding分片模式 将一个数据存储到一组水平分区或碎片.存储和访问大量数据时,这个模式可以提高可扩展性. 背景和问题 由一个单一的服务器托管的数据存储区可能会受到以下 ...
- canvas练习 - 七巧板绘制
用到的方法: 注意点: stokeStyle等样式要在stroke前边 如果最后只有一个stroke或者fill,那么只填充最后一次路径的,之前的也会画出来但是没有填充看不到.所以每次begin+cl ...