空间范围内检索方案

很早就有意向写一篇记录范围内检索的摸索过程,这里以数据量为主线展开三个方面,自己在项目以及demo过程中先后实践过。

范围内检索,一个文本的地址,想要实现空间范围的检索,必须具有一个属性,就是经纬度,这里默认的数据格式如下:

经纬度信息,特定的属性信息

应用场景是我们给定一个地址A,在上面的数据库中检索出地址A周围的信息,用于满足业务场景。

(1)数据量在十万以内

此时的数据量非常少,经纬度存储可以分为两个字段来搞,X和Y分别代表经度和纬度,直接存储在mysql中即可

地址A---地址A的经纬度信息---通过具体的范围信息划定一个矩形--获取矩形的对角线两个点(A1,B1)和(A2,B2)

通过简单的矩形内部计算就可以满足范围内检索,sql形式如下:

A1<X<A2

B1<Y<B2


(2)数据量在100W到300W左右

这时候数据存储还在mysql中,只不过不用上面的办法了,而是利用mysql对于空间数据的扩展来满足需求。

例如下面的sql,用来创建空间数据point的一张表,注意engine需要使用MyISAM(因为这个引擎才能加上空间索引),还有就是需要加索引的那个字段必须为非空。

create table search_point(
id bigint not null auto_increment,
biz_order_id bigint(32),
county_id int ,
address varchar(256),
gmt date ,
latlng point not null,
primary key(id)
)engine=MyISAM default charset=gbk;
 

添加空间索引,添加索引后才能使用空间函数进行索引。

alter table search_point add spatial index(latlng);
 

下面通过空间函数来实现检索,百万级别的数据,返回结果基本在毫秒级别

例如下面的ibatis函数

<select id="getInfoBylatlng" resultMap="searchResultMap">
select biz_order_id,county_id,address,AsText(latlng)
from lg_search_point
where
MBRContains(GeomFromText('POLYGON((
$swlat$ $swlng$,
$selat$ $selng$,
$nelat$ $nelng$,
$nwlat$ $nwlng$,
$swlat$ $swlng$
))'),latlng)
and gmt=#selectdate#
</select>
  

(3)数据量在1亿+左右

这个级别的数据量就不是mysql能够解决的了,分库分别暂时没有一个分库分别的主键,所以要通过nosql来搞定,在尝试过程中用到了hbase来作为数据存储。

大体思路是:通过对经纬度信息进行geohash编码,把二维的空间问题转化为一维的代数问题。

经纬度---geohash编码

然后geohash编码作为hbase的rowkey来设计,geohash编码值有个特定就是前缀相同的位数越多,越相近。

此时正好利用hbase中rowkey的prefixfilter来满足需求。

上述为空间数据检索的三个实践,数据量不同,可以选择不同的场景。

猜你喜欢

转载自iamzhongyong.iteye.com/blog/1537114