我们需要获取附近的人\物\机构,一般使用经纬度坐标来实现,在数据库中对每条字段都有一个经纬度的坐标,那么我们可以在查询的时候采用范围查询的方式来实现:
select * from XXX where X>=x1-x2 and x<=x1+x2 and y>=y1-y2 and y<=y1+y2;
这样通过范围查询得到具体的字段,但是随着表数据的增多,范围查询的效率会降低,那么我们应该对x,y建立索引来提高性能。
但是我想着如果这个表的数据不断增大,一个用户可以创建5个家庭,总共用户有400W个那么全部创建家庭最多会存在2亿条数,那么这样利用mysql范围查询依然很慢。 通过查阅资料发现redis有一种geoHash类型的数据结构。
geo编码指的是将经纬度采用某种分割形式变成2进制串,数值越接近代表地理上也能越接近。
我们将经纬度转成geo存入geohash中,geohash内部也是一个跳表实现的zset,将我们的key可以指定为字段的ID,source为我们使用geo处理后的geohash,redis还支持GEORADIUS命令来获取指定坐标,指定半径范围内的元素。我们拿到这个值包含key和source,拿到key利用key去数据库查询可以直接提高效率。因为ID有主键索引,查询速度较快且不需要回表。
相比起将x,y建立索引的方式,采用redis相当于将索引放到的redis里面,利用geo的特性O(logn)的时间复杂度就能查询出对应的ID,再通过ID去数据库取值可以极大程度提高性能。