一直在琢磨LBS,期待可以发现更好的方案。现在纠结了。

简单列举一下已经了解到的方案:
1.sphinx geo索引
2.mongodb geo索引
3.mysql sql查询
4.mysql+geohash
5.redis+geohash

然后列举一下需求:
1.实时性要高,有频繁的更新和读取
2.可按距离排序支持分页
3.支持多条件筛选(一个经纬度数据还包含其他属性,比如社交系统的性别、年龄)

方案简单介绍:
1.sphinx geo索引
支持按照距离排序,并支持分页。但是尝试mva+geo失败,还在找原因。
无法满足高实时性需求。(可能是不了解实时增量索引配置有误)
资源占用小,速度快

2.mongodb geo索引
支持按照距离排序,并支持分页。支持多条件筛选。
可满足实时性需求。
资源占用大,数据量达到百万级请流量在10w左右查询速度明显下降。

3.mysql+geohash/ mysql sql查询
不支持按照距离排序(代价太大)。支持分页。支持多条件筛选。
可满足实时性需求。
资源占用中等,查询速度不及mongodb。
且geohash按照区块将球面转化平面并切割。暂时没有找到跨区块查询方法(不太了解)。

4.redis+geohash
geohash缺点不再赘述
不支持距离排序。支持分页查询。不支持多条件筛选。
可满足实时性需求。
资源占用最小。查询速度很快。

------update
补充一下测试机配置:
1TB SATA硬盘。8GB RAM。I3 2350 双核四线程




图解MongoDB地理位置索引的实现原理

日期:2011-6-9 作者:nosqlfan    我要评论

 |   | 
  • 投稿 
  • 打印

导读:本文介绍了MongoDB地理位置索引的实现原理,地理位置索引支持是MongoDB的一大亮点,这也是全球最流行的LBS服务foursquare选择MongoDB的原因之一。

关键词:MongoDB 地理图形 索引 数据库 B+ Tree 

  地理位置索引支持是MongoDB的一大亮点,这也是全球最流行的LBS服务foursquare 选择MongoDB的原因之一。我们知道,通常的数据库索引结构是B+ Tree,如何将地理位置转化为可建立B+Tree的形式,下文将为你描述。

Advertisement
再提LBS经纬度搜索和距离排序,求更优方案_第1张图片

  首先假设我们将需要索引的整个地图分成16×16的方格,如下图(左下角为坐标0,0 右上角为坐标16,16):

  

  单纯的[x,y]的数据是无法建立索引的,所以MongoDB在建立索引的时候,会根据相应字段的坐标计算一个可以用来做索引的hash值,这个值叫做geohash,下面我们以地图上坐标为[4,6]的点(图中红叉位置)为例。

  我们第一步将整个地图分成等大小的四块,如下图:

  划分成四块后我们可以定义这四块的值,如下(左下为00,左上为01,右下为10,右上为11):

01 11
00 10

  这样[4,6]点的geohash值目前为 00

  然后再将四个小块每一块进行切割,如下:

  

  这时[4,6]点位于右上区域,右上的值为11,这样[4,6]点的geohash值变为:0011

  继续往下做两次切分:

  

  

  最终得到[4,6]点的geohash值为:00110100

  这样我们用这个值来做索引,则地图上点相近的点就可以转化成有相同前缀的geohash值了。

  我们可以看到,这个geohash值的精确度是与划分地图的次数成正比的,上例对地图划分了四次。而MongoDB默认是进行26次划分,这个值在建立索引时是可控的。具体建立二维地理位置索引的命令如下:

  db.map.ensureIndex({point : "2d"}, {min : 0, max : 16, bits : 4})

  其中的bits参数就是划分几次,默认为26次。

原文出处:http://blog.nosqlfan.com/html/1811.html