地理位置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 ...
随机推荐
- React Native汇错归纳(持续更新中……)
1.2017-10-25: 报错信息:“Cannot find entry file index.android.js in any of roots…..” 解决方法: 1.首先从虚拟机中找问题:看 ...
- oracle如何链接到另外一个数据库DB_LINK
命令创建从一个库连接的另外一个库: create database link DB_XXX --创建连接的名字connect to db_xxx --数据库名identified by DB-XXX ...
- PowerDesigner学习笔记
首先是概念模型个物理模型的区别,概念模型,即ConceptualDataMode,是没和具体类型的数据库(如SQL Server.MySql)的对应,是一种抽象的,而物理模型是指定了某种具体类型的数据 ...
- GitHub上整理的一些工具【转载】
技术站点 Hacker News:非常棒的针对编程的链接聚合网站 Programming reddit:同上 MSDN:微软相关的官方技术集中地,主要是文档类 infoq:企业级应用,关注软件开发领域 ...
- WP8.1学习系列(第十一章)——中心控件Hub开发指南
在本文中 先决条件 什么是中心控件? 添加中心控件 将分区添加到中心 添加交互式分区头用于导航 将展示磁贴添加到中心 使用窄应用中的垂直中心 借助中心使用语义式缩放视图 摘要和后续步骤 重要的 API ...
- WEB中会话跟踪[转]
今天晚上去华工参加睿智融科的笔试,问到web会话跟踪,一脸懵比,这个词听都没听过,回来后百度下,发现其实会话跟踪的内容我基本都了解的~_~ 转自:http://www.cnblogs.com/gaop ...
- 【github】添加 ssh 秘钥
1 生成秘钥 打开shell 备注: 123@example.com 为邮箱地址 ssh-keygen -t rsa -C "123@example.com" 此处选Y ,其他都是 ...
- 关于SQL优化(转载,格式有调整)
一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...
- javaweb基础 01--JSP取得绝对路径应用
1.相关函数说明 * request.getScheme() 等到的是协议名称,默认是http * request.getServerName() 得到的是在服务器的配置文件中配置的服务器名称 比如: ...
- 异构GoldenGate 12c 单向复制配置
1.分别在windows2008.linux平台部署oracle 11.2.0.4 2.分别在windows2008.linux平台部署gg. 2.1 windows平台: gg的安装目录位 C:\o ...