文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/
1.背景
多个项目中实现范围(圆)搜索的方案为:依赖库表中的X和Y字段构造一个矩形查询范围,再通过几何计算范围中的数据到指定坐标的距离是否在阈值半径中,最后返回阈值中的数据。
该方案有几个优点:
无需对数据预处理,仅通过sql就可以实现,实现方式简单。
数据库环境中,通过数字搜索比通过字符串搜索效率更高,占用的CPU更少。
但是,该方案在表数据量庞大的情况下,通过X和Y两个字段,并且有四个查询条件,对性能有一定损耗。
在之前我写过一篇关于Geohash编码研究的文章WebGIS中GeoHash编码的研究和扩展,这里提到了一种将X和Y以哈夫曼原理编码成一维字符串的方案。那么这里如果我们使用geohash编码方案来优化查询效率是否有用?
2.基于GeoHash编码的范围查询
2.1需要解决的点
基于GeoHash编码原理,将编码对象从经纬度数据扩展到也支持平面坐标数据
由于编码值对应的是一个范围,如果查询坐标落入在范围的角落,仅通过相同字符串匹配可能导致查询结果不全,这里需要重构查询范围
根据查询的容差范围,可以计算出该范围所得应的geohash字符串位数
2.2解决思路
针对平面坐标:将编码范围改变成该地图平面坐标真实范围,基于哈夫曼编码规则进行计算,最后使用base32编码成字符串。
针对查询范围:以查询点为中心通过查询范围构造出查询范围矩形,利用目前查询范围所对应的hash编码长度所对应的精度,利用该精度将矩形进行切割,然后对格网分别编码。
geohash长度所对应的真实精度:基于编码规律,经度的bit长度可以为奇偶,但是纬度的bit长度必须是偶数,反算出经度和纬度的bit长度。然后根据经纬对范围,结合各方向的二分法次数(bit长度),即可算出经纬度此时的精度。
2.3方案实现
这里重点给出查询搜索代码,即通过hash长度对应的精度、查询范围参数,进行网格切分和编码。
/***
* 通过传入指定范围、指定坐标、查询范围和geohash长度,返回查询范围中对应的所有geohash编码
* @param minX
* @param minY
* @param maxX
* @param maxY
* @param X
* @param Y
* @param geohashLength geohash字符串编码长度
* @param searchRange 查询范围,如果是平面坐标系100M则传入100,经纬度坐标系0.0001度则传入0.0001
* @return</