当前位置:网站首页 > 技术博客 > 正文

网格空间索引的基本原理



文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/

  • 无需对数据预处理,仅通过sql就可以实现,实现方式简单。
  • 数据库环境中,通过数字搜索比通过字符串搜索效率更高,占用的CPU更少。

  • 基于GeoHash编码原理,将编码对象从经纬度数据扩展到也支持平面坐标数据
  • 由于编码值对应的是一个范围,如果查询坐标落入在范围的角落,仅通过相同字符串匹配可能导致查询结果不全,这里需要重构查询范围
  • 根据查询的容差范围,可以计算出该范围所对应的geohash字符串位数
  • 针对平面坐标:将编码范围改变成该地图平面坐标真实范围,基于哈夫曼编码规则进行计算,最后使用base32编码成字符串。
  • 针对查询范围:以查询点为中心通过查询范围构造出查询范围矩形,利用目前查询范围所对应的hash编码长度所对应的精度,利用该精度将矩形进行切割,然后对格网分别编码。
  • geohash长度所对应的真实精度:基于编码规律,经度的bit长度可以为奇偶,但是纬度的bit长度必须是偶数,反算出经度和纬度的bit长度。然后根据经纬对范围,结合各方向的二分法次数(bit长度),即可算出经纬度此时的精度。

这里重点给出查询搜索代码,即通过hash长度对应的精度、查询范围参数,进行网格切分和编码。

 
  • geohash编码通过不断的二分,如果有必要可以直接将精度编码至厘米或毫米级别,并且对应的编码长度不会特别长。比如,当经纬度坐标系下,即使坐标范围用全球范围(-90到90,-180到180),其厘米级的编码长度也不长。以下是此时的长度精确表:
  • 高精度编码没法使用:虽然精度到厘米编码长度也不长,但是当查询范围是1Km例如,此时编码长度只需要到2位,而查询却必须使用like去匹配,此时查询效率反而太低。
  • 不同编码长度间跨越的精度太大:比如,查询1000M和查询2000M范围所对应的编码长度可能都是2,这样导致查询的结果的个数(格网切分)可能特别多。那么此时即使对编码字段做了索引,也不一定会产生实际效果(如果使用In则索引无效,而使用OR,查询条件又过多影响sql解析等)。
  • 编码为字符串影响查询效率:geohash编码的结果是基于Base32规范进行结果编码,为字符串,影响数据库查询效率。

geohash编码由于随着地图范围不同各编码长度精度无法确定、编码只能以字符串存储等问题,在我们的业务场景上无法使用。那么,如果我们让编码精度确定、编码可以用数字替代,是否就可以达到业务场景的需要呢?

格网划分算是GIS算法中的万金油。以前博客中写过的空间索引、地理插值、影像金字塔、矢量切片等等均可以基于格网的思路去探索。这里,同样可以利用格网算法来进行编码。

  • 将地图的左上角坐标当做原点,设定好格网的长度(X方向和Y方向)
  • 传入坐标,计算坐标分别在X方向和Y方向离坐标原点的格网个数,分别为xNum、yNum
 

如果我们需要将编码转换成数字编码,那么我们同样需要设定一种规则。这里,我规定xNum和yNum都必须是八个字符串长度,不足的在前缀以0补充,最后再合并转换成整数。(注意,这里我设计以0作为前缀而不是后缀补充,是为了及时转换成数字后,以后可以通过数字将编码反转换为空间范围)

 

同样,这里也需要考虑与geohash查询时一样的情况:

  • 查询XY落在网格的边角上
  • 查询范围阈值大于网格大小 解决思路与之前相同:
 
  • 格网不宜划分太小,建议划分的比查询范围大,这样保证范围过滤查询时返回的匹配格网编码少。比如,格网大小500M,查询范围100M,查询时,在多数情况下将只返回一个编码。当然,此时基于该编码去数据库中查询,将得到更多的数据点,于是需要我们做精确的范围计算量变大。但是:将数据库压力适当转移到服务器计算是一种更划算的策略。当然,格网划的太大,也会适得其反,建议通用查询范围一两倍即可。
  • 坐标存入时,将坐标基于格网编码并同步存入到指定字段,对该字段建立索引(此时字段为长度大于16的长整型)。
  • 查询时,调用编码查询接口,获取到该XY以及查询范围下,对应的网格编码。在数据库中利用这些编码做匹配查询(粗过滤)。对返回的结果进一步做精确范围匹配(精过滤可做可不做,视需求规格而定)。

                      

                       -----欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/

                                                                           如果您觉得本文确实帮助了您,可以微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^

                               

  • 上一篇: k8s搭建redis三主三从集群
  • 下一篇: seq1m
  • 版权声明


    相关文章:

  • k8s搭建redis三主三从集群2025-04-21 14:30:04
  • usermod -s使用详解2025-04-21 14:30:04
  • 警花小说名字2025-04-21 14:30:04
  • echarts第一个点在原点2025-04-21 14:30:04
  • libxml2-devel2025-04-21 14:30:04
  • seq1m2025-04-21 14:30:04
  • windows 封装2025-04-21 14:30:04
  • windows找不到gpedit文件2025-04-21 14:30:04
  • rownum oracle用法2025-04-21 14:30:04
  • 指针数组的指针2025-04-21 14:30:04