介绍一下geohash与geotree
Geohash
Geohash 是一种将二维地理坐标(经度 Longitude 和 纬度 Latitude)编码为一个可排序的字符串的空间索引方法。由 Gustavo Niemeyer 于 2008 年提出,并被广泛用于分布式地理数据索引、近邻搜索、区域聚合等场景。
核心特征为:
- 编码结果是Base32 字符串
- 字符越多,空间精度越高
- 相近位置编码字符串有公共前缀
Geohash 编码原理
Geohash 使用经纬度交替二分的方式,将整个地球的经纬度范围不断缩小,直到定位到目标点。过程主要分为以下 4 步:
步骤 1:初始化经纬度范围
- 经度范围 lon_range = [-180, 180]
- 纬度范围 lat_range = [-90, 90]
步骤 2:交替二分编码,生成二进制序列
使用**二分法(Binary Search)**编码纬度和经度:
- 从经度开始(偶数位处理经度,奇数位处理纬度)
- 每次比较当前坐标是否大于区间中点,如果是,记为 1,否则为 0
- 并更新范围(左/右半区)
这个过程交替进行直到你得到足够数量的位,比如 5 位 * 7 字符 = 35 位。
步骤 3:每 5 位为一组,转为十进制索引
将所得的长二进制串,每 5 位一组,转为十进制,然后用 Base32 映射表替换。
步骤 4:生成最终字符串
每 5 位 → 1 个字符,共 n 个字符(通常精度为 6~9 个字符)。
Geohash优点
1. 支持空间邻近查询
- Geohash 编码相邻的区域通常具有相似前缀,适合使用前缀匹配(如 LIKE ‘wx4g0%’)实现快速范围查询。
- 特别适合在数据库中对空间对象做索引。
2. 分级精度(多级网格)
- 编码长度越长,表示区域越小,精度越高。
- 可动态控制精度,适合不同缩放层级的空间分析。
3. 文本存储,易于索引
- Geohash 是字符串格式,便于存储、索引(B-Tree、Trie)、压缩和分布式传输。
4. 无依赖的数据结构
- 不依赖复杂的空间数据结构(如 R-Tree、QuadTree),适用于轻量级地理索引服务。
5. 适合分布式系统
- Geohash 可直接用于 Sharding,例如前缀作为分片 key,天然适配大数据平台如 HBase、Elasticsearch。
Geohash的不足
1. 经纬度不均匀映射
- 纬度范围 [-90, 90],经度 [-180, 180],导致赤道附近一个 Geohash 单元的面积大于极地。
- 地球是球体,Geohash 假设平面映射,有畸变。
2. 边界误差问题
- 相邻的两个地理位置如果落在不同的 Geohash 网格单元中,会出现编码前缀差异,影响邻近判断。
- 需要额外处理“邻居格子”。
3. 形状不规则
- Geohash 网格在地图上是长方形而非正方形,且每一级的比例不均一,查询时常需额外扩大范围。
4. 二维信息压缩成一维有信息损失
- 经纬度交替合并会丢失部分空间关系(例如正方形邻域判断更复杂)。
5. 精度和效率权衡
- 长 Geohash 字符串意味着更高精度,但也带来索引增长和性能损耗问题。
总的来说,Geohash 是一种优雅的地理编码方案,它以轻量、易索引的方式,在现代数据库和分布式系统中广泛应用。然而,在面对高精度、复杂空间关系时,它也暴露出一定的局限性。因此,在实际使用中,应结合业务需求,评估其合适性,并配合如邻接格补全、R-Tree 等技术优化空间查询性能。
GeoTree
GeoTree 是一种基于空间层级划分的地理编码体系,它将地球表面按不同层级进行规则划分,并通过编码的方式表达空间单元的层级和位置关系。相比 Geohash 等网格编码,GeoTree 更强调“树结构”和“地理拓扑”的结合,适用于需要空间聚合、路径查询、空间层次建模的应用场景。
GeoTree 的思想与四叉树(QuadTree)类似,但更灵活,支持多尺度编码与空间父子继承关系表达,广泛用于如地空一体化管理、空域划分、地理分区治理等空间应用。
核心特征:
- 每个节点表示一个空间区域,节点 ID 为可排序的字符串或整数
- 子区域编码在父编码基础上扩展(继承性编码)
- 层级结构清晰,便于表示“包含关系”和层次聚合
- 支持三维空间索引(经度、纬度、高度)
GeoTree 编码原理
GeoTree 并非采用经纬度交替压缩为二进制,而是按照空间网格划分规则,分层递归构建编码。过程一般如下:
步骤 1:定义根层空间范围(Level 0)
- 将地球划分为若干大格(如全球 8 区或全球 6 面体)
- 每个大格分配一个唯一编码(如 “1”、“A”、“R0”)
步骤 2:递归划分子区域(Level 1~n)
- 每个区域根据固定或可变规则继续划分为子区域(如 4 等分、9 等分、3D 立方等)
- 子区域编码在父编码基础上追加子代标识(如 “1-3” 表示根节点 1 的第 3 个子区)
步骤 3:形成空间编码树
- 所有区域构成一棵空间树:根为地球、分支为区域、叶子为最小单元
- 编码如 A-1-2-0 表示:区域 A → 子区 1 → 子区 2 → 子区 0
步骤 4:支持三维编码(可选)
- 对于需要高空建模的场景,每层子区可增加“高度切分”,编码如:A-1-2-0-H2
GeoTree 的优势
1. 天然支持空间层次结构
- 每个编码天然携带层级信息,如 A-2-3 表示第 2 层、第 3 区
- 支持区域归属、包含、父子导航等空间树操作
2. 邻接关系明确,便于空间合并
- 可快速判断相邻区域是否有共同父节点,从而实现区域合并、聚合分析
3. 便于多尺度查询
- 查询精度可控制在某一层级,例如只查询第 3 层的所有编码
4. 编码形式灵活
- 可以使用字符串(如 “E-3-1”)或整型编码(如位运算 0b010101)支持高效索引
5. 支持三维空间编码
- 除经纬度之外,GeoTree 可扩展高度维度,适用于低空空域、建筑分层、空间管网等场景
6. 更强的空间拓扑表达能力
- 相比 Geohash 的“前缀相似”,GeoTree 明确建模空间父子关系,有助于空间推理和规划控制
GeoTree 的不足
1. 空间分区规则需自定义
- 没有标准化的编码划分规则,不同业务可能用不同树型划分方式
2. 区域形状不规则
- 编码背后代表的空间单元可能非正方形(视分割策略),可能导致某些计算复杂
3. 实现成本略高
- 相比 Geohash 纯字符串压缩,GeoTree 需要维护树结构、支持路径解析和层级操作
4. 邻接格查找略繁琐
- 查找空间邻居不像 Geohash 可以通过简单变换字符实现,而需要访问同层兄弟节点
GeoTree 是一种结构化、层级化、拓扑清晰的地理编码体系,它从空间组织结构出发,更适合表达“地理分区与归属”这一类场景。在复杂区域管理、空间权限控制、多尺度数据建模等领域,比 Geohash 更具表达力。
然而,由于 GeoTree 没有统一标准实现,初始设计需结合业务规则规划编码体系。在面向大规模分布式查询的场景下,GeoTree 可与 Geohash 等轻量编码联合使用,取长补短,实现高效、结构清晰的空间信息处理。