一个技术博客

LBS 初试

本文由 Tim 于 2016-06-30 11:13:06 发表

位置服务(LBS,Location Based Services)又称定位服务,LBS是由移动通信网络和卫星定位系统结合在一起提供的一种增值业务,通过一组定位技术获得移动终端的位置信息(如经纬度坐标数据),提供给移动用户本人或他人以及通信系统,实现各种与位置相关的业务。

­LBS相关的应用随处可见. 日常使用的微信、陌陌、地图、订餐等APP。查找附近(陌生人、餐馆、网吧、银行…), 数据量少可以在经纬度上加减进行初步筛选,然后计算距离排序,而需要在大量经纬度数据中检索的时候,就不太可行了。
博主总结了下常见的LBS实现方案

1、Mysql使用GeoHash转换成字符串存储
2、Postgresql的PostGis插件,支持空间计算
3、Mongodb 自带距离计算
4、Redis 自带距离计算
5、Mysql spitial
6、lbs云服务(百度、高德…)、基于搜索引擎的

测试机器配置均为单核 2G ram,数据库均为默认配置,结果仅供参考

一、GeoHash

GeoHash将二维的经纬度按规则转换成字符串存储,例如经度:114.775123,纬度:22.588995转换成的GeoHash字符串为ws18eb0wqjye,对GeoHash字符串建立索引,查询的时候对GeoHash字符串进行前缀匹配,

select id,lat,lon,geohash from lbs where geohash like ‘ws18eb%’,前缀匹配长度越长,距离越近。

原理和具体实现方式移步:GeoHash核心原理解析开发LBS应用之 根据一点的经纬度实现附近点的查询 – geohash

php添加GeoHash模块:https://github.com/shenzhe/geohash

在Mysql测试,使用php随机生成经度114~115,纬度22~23内1000w条数据,GeoHash列建索引

LBS 初试

实测效率如下
在like ‘ws18eb%’时,因为数据少(),速度很快,此时6位匹配到±0.61km左右LBS 初试

LBS 初试

当like ‘ws18e%’时,数据大概在,6位匹配到±2.4km左右,这个时候就慢了。like 前缀还是挺快的,慢的是计算距离然后排序这里,当然,计算公式还可以稍微优化下筛选出更少数据,为了方便使用,也可以写成存储过程LBS 初试

前缀长度不同,取出的记录也会有区别,这是因为GeoHash按照矩形区域划分导致的。

二、PostGis

PostGIS is a spatial database extender for PostgreSQL object-relational database. It adds support for geographic objects allowing location queries to be run in SQL.

PostGIS 是 PostgreSQL 关系数据库的空间操作扩展,支持空间对象,可以直接计算距离

测试数据如下,多了一列the_geom,使用PostGIS内置函数ST_GeomFromText(‘POINT(lon ,lat)’),4326)转换生成

LBS 初试

对the_geom建立gist索引

测试效率如下,配合order by <->非常快

LBS 初试

LBS 初试

由于<->类似近似值的效果,因此还是存在数据不精确的问题,不过大部分时候是足够用的,当limit 越来越多的时候,时间消耗也会越来越大

 

三、Mongodb

MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。
MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
Mongodb支持二维空间索引,使用空间索引,Mongodb支持一种特殊查询,如某地图网站上可以查找离你最近的咖啡厅,银行等信息。

测试数据如下LBS 初试

查找最近的10个,耗时1.6s
LBS 初试

查找最近的100个,耗时5.3sLBS 初试

Mongodb查询出来的数据比较精确

四、Redis

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库。之前的Redis需要dynamic-redis-unstable版并安装模块才支持,最新版的Redis(3.2)已经众望所归的添加了geo,支持GEORADIUS WITHDIST,在内存上计算效率也比较高。

以上测试数据均一致,1000w条,由于是无序集合,因此在Redis中测试数据是无序的。

LBS 初试

查找1km内的10条记录,非常快,时间小于0.5s,就没显示时间信息

LBS 初试

查找10km内101条记录,耗时0.53s,相当暴力

LBS 初试

Redis因为是基于内存的,在内存中查找计算效率会非常高,而且精确

五、Mysql spitial

Mysql空间函数索引在Myisam引擎很早之前就有了,5.6引入st_distance等函数,可以计算2点间的距离,5.7.5之后InnoDB引擎也支持空间索引了,
数据如下,1000w条,和以上测试数据一致,spa字段类型为point ,建立spatial索引

LBS 初试

查找耗时10s左右,因为需要先进行计算排序后limit,因此10条和100条记录基本一致,可以进一步控制数量后计算,速度会有较大提升

LBS 初试

LBS 初试

性能不高,不过博主在测试中发现速度也可以优化到0.5s左右,怎么做到呢(不是缓存的缘故),一般人先不告诉他LBS 初试

LBS 初试

六、lbs云服务(百度、高德…)、基于搜索引擎

 

此部分博主暂还未测试,看描述应该是支持的,将经纬度数据存入云,通过api调用即可,百度LBS云描述如下
LBS.云是百度地图针对LBS开发者推出的平台级服务,结合已有的地图API和SDK服务,通过开放服务端存储和计算能力,提供海量位置数据的实时存储、检索、展示一体化解决方案。

类似还有高德等lbs云服务商。

搜索引擎ElasticSearch官网 https://www.elastic.co/,lucene 等,使用搜索引擎检索速度也会很快,读者可以自行研究,此部分以后测试过再补上。

总结:需要高精确度和速度可以使用Redis,基于内存,性能可谓暴力,对精确度不是很敏感可以考虑mysql geohash实现,不改变mysql现有架构,5.7.5后mysql支持spatial索引可以直接使用MBRcontains先检索后排序,在数量不多的情况下,速度也可以接受,mongodb和postgis按需使用,另外还可以使用lbs云服务,投资小,见效快,O(∩_∩)O~

欢迎转载,转载请注明出处!Tim » LBS 初试

点赞 (10)or拍砖 (1)
分享到:更多 ()