1. 原因

这一切还得从前段时间接到的一个需求讲起。
业务方需求离线核算一批A邻近5公里内的B,并核算聚合B的相关指标,进行展示。

嗯,听起来很合理。

2. 问题

虽然在进行前期评价时,就已经预料到核算量会很大(当时的核算计划非常粗陋)。
但在实践运转过程中,仍是发现邻近5km的逻辑,核算功率过于低下(依照城市编码将数据拆分为3个任务进行并行核算,但均匀耗时仍是会到达7-10个小时,无法接受)

3. 一些尝试

3.1 第一版:

最开始的核算逻辑很粗暴:把每个城市内的A和B进行full join,然后依据经纬度逐一核算间隔,排除去超出间隔限制的调集。肉眼可见的低效。。。

我遇到的一个难题,早在1966年就已经有解决方案了...

3.2 第二版:

由于全量核算非常耗时,而且大部分B的坐标也不会常常变更,因而开始考虑运用增量核算进行优化,削减重复核算。
但在实践任务运转过程中发现,很多耗时用在了历史数据和新增数据的兼并写入,并没有有效的功率提升。

我遇到的一个难题,早在1966年就已经有解决方案了...

3.3 第三版:

这个时候,已经没有什么优化的条理了。只是一次偶然的搜索,让我发现了一个全新的完成逻辑。(没错,面向google编程)

我遇到的一个难题,早在1966年就已经有解决方案了...

一个周五的晚上,脑袋里思索着经过经纬度核算间隔的逻辑,突然一个主意呈现:已然经纬度可以进行间隔核算,是否意味着经纬度的数字也是和间隔有着一定的转化联系,比如经度小数点后1位,代表间隔xx公里?

带着这个疑问,我发现了这两篇文章。

我遇到的一个难题,早在1966年就已经有解决方案了...

其中 高效的多维空间点索引算法 — Geohash 和 Google S2介绍的案例,与我的需求非常相似。(大神的文章值得好好阅览)

里面说到的geohash算法,则是1966年就有人提出的一种将经纬度坐标点进行一维化编码的处理思路。而后续的google的s2、uber的h3,均是在此设计理念的基础上优化而来的。

这种算法的实质就是对地球的每一块区域都进行编码(精度可调),也就是一个编码代表着一段经纬度范围内的区域。

那么接下来问题就简略了,找到适宜的编码计划以及精度参数,测试验证即可。

具体的计划挑选就不重复了。可以参阅这个帖子:geohash、google s2、uber h3三种格网体系比较

我这边终究挑选的是h3(h3-pyspark)。

4. 终究处理

第一步:将A的经纬度依照需求的精度进行编码,再获取该编码邻近x公里的区域编码调集。

我遇到的一个难题,早在1966年就已经有解决方案了...

第二步:将B的经纬度依照相同的精度进行编码。

第三步:将两个数据集inner join,即可取得符合要求的调集。

是的,就是这么简略。(摊手)

我遇到的一个难题,早在1966年就已经有解决方案了...

5. 总结

经过这次的问题处理,学习到了这类场景的通用处理计划,受益匪浅。

6. 参阅文章

高效的多维空间点索引算法 — Geohash 和 Google S2
彩云天气地理查询优化(2): 行政区划查询
geohash算法
geohash、google s2、uber h3三种格网体系比较
h3-pyspark
Uber H3运用