跳转到主要内容
工程的博客

有效点在多边形连接通过PySpark和BNG地理空间索引

分享这篇文章
这是一个协作由陆地测量部,微软和砖。我们感谢卡里斯Doidge、高级数据工程师和史蒂夫·金斯顿高级数据科学家,陆地测量部,琳达Sheard,高级分析和人工智能在微软云解决方案架构师,他们的贡献。

这个博客提供了一个军械调查(OS)之间的合作,探索空间分区使用砖和微软的英国国家电网(BNG)。

操作系统负责设计和开发一个新的国家地理数据库(NGD)数据交付英国(GB)公共部门地理空间协议

操作系统密切合作与砖和微软的架构策略和数据工程能力,支撑NGD作为核心数据服务平台的一部分。bob体育客户端下载这个平台可bob体育客户端下载以让操作系统迁移进行地理空间数据处理一直以来都on-prem机器在单线程的进程和应用程序中,如FME云计算,可用和可伸缩的随需应变,因此,实现地理空间数据的处理和分析。操作系统使用Azure砖Apache火花™功能添加到云平台,这带来了机会重新思考如何优化数据和方法进行大规模地理空间连接使用并行处理。bob体育客户端下载

适当的索引空间数据是这样的优化工作的一个方面,它不仅仅停留在选择索引。这个博客的重点是如何设计一个流程,使最大使用提供的索引允许优化Azure砖来优化数据从磁盘加载的方式在扩展地理空间连接。

有各种网格索引,如BNG Geohash,超级的H3,谷歌的S2与标识符空间世界划分为垃圾箱。在一些专门开发的背景下,现代geoanalytics,因此倾向于支持库和实例相关联的用在这种情况下,英国国家电网索引系统于1936年定义,已经深深植根于英国地理空间数据的生态系统,但尚未开发,可为geoanalytics规模。我们这里的二级动力,因此,表明它可以直接使用优化空间连接,避免了需要英国的地理空间数据集转换成其他索引系统。我们的团队实现了一个镶嵌技术,多边形分解成简单的几何图形在给定BNG指数有界的存在。通过有效地限制索引空间比较和空间谓词评估,取得了引人注目的查询性能的方法。

点包容:有多难?

有多难确定一个点是否在多边形(PIP) ?如何判断一个点是否包含在一个多边形已经回答年前。这个事实可以引入偏见,让我们过早下结论说,“它是很容易的;它已经被解决了。”然而,随着技术的进步和并行系统的引入,我们发现自己问这个同样的问题,但在一个新的环境。上下文是使用脉冲作为连接关系在大(地理)数据。新问题是确保我们高水平的并行性的方法。不幸的是,旧的答案不再适用在这个新的环境。

我们可以把连接关系的配对问题。我们可以观察到它有两个数据集包含行匹配的行从其他数据集同时满足连接条件。连接关系的复杂性O (n *米)或俗称的笛卡儿积(复杂性)。这是最坏的连接关系复杂,简单来说,意味着我们需要比较每个记录从一个数据集和每个记录的其他数据集来解决所有匹配。许多系统实现技术和启发式推动这种复杂性较低的水平。然而,这是底线,我们将开始考虑从这个基线。

的环境中操作系统的地理空间数据处理、最常见的一种脉冲连接通常是所有地址之间进行几何图形(约。(约3700万)和所有大型建筑物多边形几何图形。在GB 4600万)。

地址和建筑物之间的点包容
图一个

(不)隐藏的成本?

在讨论加入关系复杂性,我们取得了一个监督。传统的复杂性假设每一对决议的固定成本,也就是说,到达一个结论的成本每一对匹配或不匹配的记录在连接操作,我们将调用O(加入)。加入的真实成本O (n *米)* O(加入)。在传统的等价类的关系,我们只是在考虑是否加入键左边匹配连接键在右边,我们假设O(加入)O (1)或者简单地说,比较的成本是一个算术运算,它是恒定的。这并非总是如此;例如,加入一个字符串比较是更昂贵的比两个整数之间的等价性。

但是皮普,相对的成本如何?使用最广泛的算法回答是皮普文中算法。该算法的复杂性O (v),v是多边形的顶点的数量问题。该算法适用于凸和非凸形状,和保持相同的复杂性在这两种情况下。

增加的比较成本成本模型使我们总立方形式的复杂性。如果我们更换O(加入)O (v)v是顶点的平均数量,我们总的复杂性O (n *米)* O (v)。这既昂贵又耗时的!

更聪明地工作,而不是更刻苦!

我们可以做得更好O (n *米)* O (v)。我们可以使用火花来帮助我们击败了笛卡儿积的复杂性。火花利用散列连接。根据连接谓词,火花可以执行下列之一连接策略:

神奇的!我们可以使用火花,我们将避免最昂贵的结果,我们不能?不!不幸的是,火花将默认为PIP笛卡尔连接连接。为什么?在皮普有别于传统equi-based连接是基于一般的关系。这些连接通常称为θ加入类。这些通常是难以执行,需要最终用户帮助系统。当我们从一个不利的位置,我们仍然可以实现所需的性能。

空间索引pseudo-equivalence (PIP)

有办法让皮普是一个等价关系?严格地说不,然而,在实践中,我们可以让皮普方法效率的一个等价关系,如果我们采用空间索引技术。

空间指标有效地帮助我们指数坐标空间的逻辑分组中接近另一个几何图形表示空间。我们实现这一独特的关联点的坐标系统索引ID。这些系统允许我们代表参考空间不同层次的细节,或简单,不同的分辨率。此外,地理空间索引系统分层系统;这意味着有一个定义良好的亲子关系指数在不同级别的表示。

这将如何帮助我们吗?如果我们分配给每个几何图形它所属的指数,我们可以使用索引ID来索引ID等效为一个等价关系代理。我们将执行脉冲(或任何其他几何投影关系)只属于同一指标的几何图形。

重要的是要注意,虽然点几何图形属于一个且只有一个指数,所有其他的几何类型,包括线和多边形,可能跨度超过一组的指数。这意味着成本的解决脉冲通过索引空间关系O (k) * O (v),k指数用来表示数量的几何和v是顶点的几何的数量。这表明我们每个的价格比较增加爆炸记录复杂的几何图形为多个索引记录携带相同的几何。

为什么这是一个明智的选择吗?当我们正在增加的价格比较单一的几何图形,我们避免了一个完整的笛卡儿积,还是在大型地理空间连接。稍后我们将详细显示,索引ID索引ID连接将使我们能够跳过大量不必要的比较。

最后,数据源包含复杂几何形状不发展尽快做逐点数据源。复杂的几何图形通常代表地区,感兴趣的领域,建筑,等等,这些概念有相当稳定的时间表,对象随时间变化的变化很少,和对象变化相对较少。这意味着,当我们做的花费额外的时间进行预处理复杂的几何图形,对大部分人来说,这预处理是一个一次性的事件。这种方法仍然适用甚至频繁更新数据;我们可以跳过,当加入的数据量通过索引ID来索引ID大于增加的行数的关系用来表示一个几何。

BNG指标体系

BNG是地方坐标参考系统(CRS) (EPSG: 27700)成立于1936年,为国家映射,包括英国。与全球CRS, BNG已经安装和塑造英国、大陆的坐标投影到平面,普通方格网的原点(0,0)的西南锡利群岛的

在网格范围内,地理网格引用(或指标)是用来确定网格方块在不同的决议表示在米可以翻译和BNG以东(x)和北航(y)坐标。鉴于网格原点的位置,以东和以北值值总是正的。BNG作为主要参考系统下的所有操作系统位置数据捕获他们的国家公共任务映射,因此,被广泛采用的公共和私人用户操作系统数据操作在英国。

每一个网格都可以表示为一个多边形几何体,每条边的长度等于参考网格的分辨率。这使得BNG更容易起点地理空间数据分区策略。我们的起点是一个正方形作为构建块,和它会让很多开始考虑简单的同时不丢失的推广方法。

按照惯例,BNG网格引用表示为字符串,使用字母和西南角的一个给定的网格坐标引用一个特定的解决方案。任何参考的前两个字符是字母(前缀)(例如,TQ)识别91网格的广场之一测量100.000米(100公里)。只有55 91 100公里网格方块介绍一些在英国大陆。余下的这些方块落入英国水域。

英国国家电网100公里分辨率
图B

引用识别更细粒度的网格分辨率低于100公里将会有额外的x和y整数值后附加两个字母定位子网格是在父网格层次结构。儿童广场从左下编号从0到9(西南)的角落,在一个东风(x)和北方(y)方向。

英国国家电网100公里分辨率
图B
英国国家电网在10公里,1公里的决议
图C
英国国家电网在10公里,1公里的决议
图D

为什么BNG ?

同时有替代全局索引系统,我们可以采用这项工作,我们选择使用BNG因为:

  • BNG系统是本机操作系统的地理空间数据收集,与几乎所有的操作系统数据引用对BNG CRS (EPSG: 27700)。这包括操作系统空中影像瓦片等栅格数据集,如数字地形模型(dtm)和数字表面模型(dsm)。
  • BNG使高效检索的使用和主机托管的矢量和栅格数据分析,包括剪切或屏蔽的栅格数据推导培训深度学习应用程序补丁,作为一个例子。
  • 使用BNG避免了昂贵的世界大地转换系统(wgs - 84) (1984EPSG: 4326)或1989年欧洲地面参考系统(ETRS89) (EPSG: 4258)crs通过OSTN15网格转换。不同crs实现他们的地球模型使用不同的参数,和全球系统(例如,WGS84)将显示一个偏移量相比,一个本地系统(例如,BNG)。这种转换的真实成本反映在操作系统这一事实OSTN15出版,一个包含大约15 mb修正文件。175万参数采用卫星坐标和BNG坐标之间的变换准确。

由于GB-local操作系统试图解决的问题的本质,BNG是一种自然选择。在更多的全局上下文的情况下,我们应该转换我们的关注H3S2成为全球选择更合适。

BNG空间划分策略

空间划分策略定义了一个方法将地理空间数据分割到非重叠区域。BNG网格方块在不同的决议在英国提供非重叠区域。通过检索BNG指标,涵盖几何图形我们可以使用索引属性搭配加入关键行然后只测试一个空间谓词在这些集中的行(例如,几何相交的几何B还是几何包含几何B)。

这是非常重要的!把原始数据分解为地理空间数据集中的部分“高度平行”,和使我们的问题,因此,非常适合火花/ PySpark。我们可以将不同的数据块发送给不同的机器,只比较当地的部分数据,可能会加入一个到另一个地方。有小点检查建筑在伦敦包含在曼彻斯特的一个地址。地理空间指标是我们的方式来传达这种直觉的机器。

基线

我们使用Python和PySpark给生活带来我们的解决方案。操作系统提供的逻辑转换提供的坐标经常和北航独特BNG索引ID。最后,为了确保一个公正的输出,我们使用一个随机点和多边形的随机数据集的数据集;1000万点散落在GB,境内100万多边形被分散在同样的方式。生成一组多边形数据,我们已经加载一套GeoJSON dataframe火花,我们使用一个随机函数与一个生成器函数(爆炸)来生成一个公正的数据集。由于随机性引入数据,应当期望点和多边形之间的关系是多对多的。

基线算法用于我们的考虑是天真的加入,会导致非θ加入。这种方法将执行时间,被评价为一个嵌套循环联接播放。

指向多边形天真的加入
图E

广播嵌套循环联接运行非常缓慢。这是事实,原因是评估同样笛卡尔连接。每个point-polygon对评估对皮普关系加入之前解决。结果是,我们需要加入十亿比较10万点到1万多边形。注意,这两个数据集是大到足以被称为大数据。

mlflow输出天真加入基准——运行时在几秒钟内
图F

我们使用MLflow进行一系列的天真加入评估基线性能我们试图超越。天真的方法,最大的加入我们能够成功执行1万点到10万多边形。数据量的进一步增加导致我们的火花工作没有产生所需的输出。这些失败是由于实现工作负载的性质我们试图运行。

让我们框架的问题

如果我们代表我们所有的几何图形,无论其形状,与相应的BNG-aligned边界框吗?边界框是一个矩形多边形可以符合原文的整体几何。如果我们说边界框表示为一组BNG指数在给定的决议,覆盖同一区域。

通过英国国家GridBNG多边形的边界框表示
图G

现在我们可以执行连接通过一个更优化的θ加入。我们只检查一个点是否在多边形通过皮普关系如果一个点落入一个BNG指数用于表示多边形。这样可以减少我们的加入工作由多个数量级。

为了生产说BNG指数,我们使用下面的代码;请注意,bng_to_geom, coords_to_bng bng_get_resolution功能不提供这个博客。

shapely.geometry进口盒子#辅助函数来检索第一个邻国# BNG指数的细胞defnext_horizontal(bng_index,决议):x, y = bng_to_geom (bng_index)返回coords_to_bng (x +决议,y,分辨率)#辅助函数来检索第一个邻国# BNG指数细胞的底部defnext_vertical(bng_index,决议):x, y = bng_to_geom (bng_index)返回coords_to_bng (x, y-resolution分辨率)#填充函数,表示输入几何的一组指标#对应区域的边界框的几何表示defbng_polyfil(多边形,决议):(x1, y1, x2, y2) = polygon.boundsbounding_box =盒(* polygon.bounds)lower_left = coords_to_bng (x1, y2,分辨率)队列= [lower_left]结果=()参观了=()队列:指数= queue.pop ()index_geom = shapely.wkt.loads (bng_to_geom_grid(指数,“WKT”))十字路口= bounding_box.intersects (index_geom)如果十字路口:result.add(索引)n_h = next_horizontal(指数、分辨率)如果n_h访问:queue.append (n_h)n_v = next_vertical(指数、分辨率)如果n_v访问:queue.append (n_v)visited.add(索引)访问= []返回结果

这段代码确保我们可以无损地代表任何形状。我们使用BNG指数候选人相交关系,避免盲点的原始几何表示。注意,更有效的实现是可能通过使用包含关系和质心点;这种方法是唯一可行的是否可以接受的假阳性和假阴性。我们假设的存在bng_to_geom函数,给定一个BNG索引ID可以产生一个几何表示,bng_get_resolution函数,给定一个BNG决定选择的分辨率和索引IDcoords_to_bng返回一个函数,考虑到坐标BNG索引ID。

多边形边界框表示基准——运行时在几秒钟内
图H

我们运行我们的多边形边界框表示BNG指标体系的不同分辨率和不同大小的数据集。注意,运行这个过程失败一直低于100号决议。在这些输出决议米表示。一致的失败的原因在代表的决议可以找到低于100米;一些多边形(由于随机性质)比其他的大得多,而一些多边形是由一组12个指标,其他多边形可以表示为成千上万的指标,这可能会导致一个大的差距在计算和内存需求在分区之间的火花工作产生这些数据。

我们省略了因为这个点的基准数据集转换是一个相对简单的操作,不会带来任何新行;只添加一个列,不同的分辨率不影响执行时间。

双方的加入是用相应的BNG表示表示,所有我们要做的就是执行调整后加入逻辑:

@udf (“布尔”)defpip_filter(poly_wkt、point_x point_y):有条理的进口wkt有条理的进口几何多边形= wkt.loads (poly_wkt)点=几何。点(point_x point_y)返回polygon.contains(点)defrun_bounding_box_join(polygons_path, points_path):多边形= spark.read。格式(“δ”).load (polygons_path)多边形= polygons.select (F.col (“id”),F.col (“wkt_polygon”),F.explode (F.col (“bng_set”).alias (“bng”))点= spark.read。格式(“δ”).load (points_path)返回polygons.join (点,= (“bng”),如何=“内心”)。(pip_filter (“wkt_polygon”,“经常”,“北航”))#连接数据集上运行一个动作来评估加入运行时run_bounding_box_join (polygons_path points_path) .count ()

这些修改我们的代码导致了不同的火花执行计划。火花现在能够首次运行基于BNG指数排序合并连接ID和大大减少的总数比较。此外,每一对比较string-to-string比较远短于一个脉冲的关系。第一阶段将生成所有加入组候选人。我们将执行PIP关系测试组候选人解决最终的输出。这种方法可以确保我们限制的次数PIP操作运行。

指向多边形边界框加入
图我

执行计划,我们可以看到,火花是执行不同的操作相比,幼稚的方法。最值得注意的是,火花现在执行排序合并连接,而不是广播嵌套循环连接,这是让很多效率。我们现在执行大约1.86亿PIP操作而不是十亿年。这就允许我们运行更大的连接有更好的响应时间,同时避免任何突发故障,我们经历了天真的方法。

指向多边形边界框加入基准——运行时在几秒钟内
图J

这个简单但有效的优化使我们运行一个PIP加入1000万点至100万多边形在大约2500秒。如果我们比较基线执行时间,最大的加入我们能够成功执行1万点到10万多边形,甚至加入需要大约1500秒在相同的硬件上。

分而治之

运行数据集在几百万行域之间的连接是伟大的;然而,我们最大的基准加入了将近45分钟(2500秒)。在世界上我们想要运行特设在大量地理空间数据分析,这些执行时间太缓慢。

我们需要进一步优化的方法。第一个候选人优化我们的边界框表示。如果我们通过边界框代表多边形,我们有太多的假阳性指标,即。指数,与原来的几何不重叠。

BNG指数不与原来的几何重叠
图K

优化部分的代码的方法是简单地使用在我们polyfill相交函数调用方法的原始几何。

defk_ring(bng_index):x, y = bng_to_geom (bng_index)增量= bng_get_resolution (bng_index)邻居= [[x-increment y +增量],[x, y +增量],[x +增量,y +增量)[x-increment y], [x +增量,y],[x-increment, y-increment], [x, y-increment], [x +增量,y-increment]]邻居= [coords_to_bng(我0),我1),增量)邻居)返回邻居defbng_polyfil(多边形,决议):shapely.geometry进口盒子开始= get_starting_point(多边形,分辨率)队列= k_ring(开始)结果=()参观了=()队列:指数= queue.pop ()如果polygon.intersects (shapely.wkt.loads (bng_to_geom_grid(指数,“WKT”))):result.add(索引)nk_ring(指数):如果n参观了n队列:queue.append (n)visited.add(索引)访问= []返回结果

这种优化,利用成本增加相交调用,将导致更小的结果指标集和将使我们连接运行得更快,由于小加入表面

BNG指数与原始几何相交
图左

第二优化我们可以使用表示分解为两套指标。并不是所有的指标都是平等的在我们的表示。指数的接触边界多边形需要脉冲过滤索引索引后加入。指数,请勿触摸多边形的边界和属于表示不需要任何额外的过滤。任何时候,落入这样一个指数绝对属于多边形,在这种情况下,我们可以跳过PIP操作。

BNG指数包含的原始几何
图米

我们可以实现的第三个和最后一个优化是马赛克的方法。而不是将完整的原始几何与属于的指标集的每个索引联系多边形边界(边境),我们只能跟踪感兴趣的部分。如果我们相交的几何表示和多边形指数问题,我们得到的地方表示多边形;只有这部分的原始多边形的面积指数的相关问题。我们称这些作品为多边形芯片。

代表多边形边界的芯片
图N

从优化角度多边形芯片有两个目的。首先,他们大大提高PIP过滤器的效率发生index-to-index加入后执行。这是由于这样的事实,射线跟踪算法运行在O (v)的复杂性和个体芯片平均少一个数量级比原始几何顶点。其次,芯片的代表性远小于原来的几何形状,因此,我们拖着更少的数据作为洗牌阶段的一部分在我们的排序合并连接阶段。

把所有这些一起收益率以下代码:

defadd_children(队列、访问索引):nk_ring(指数):如果n参观了n队列:queue.append (n)返回队列defbng_polyfil(多边形,决议):开始= get_starting_point(多边形,分辨率)队列= k_ring(开始)结果=()参观了=()队列:指数= queue.pop ()index_geom = shapely.wkt.loads (bng_to_geom_grid(指数,“WKT”))十字路口= polygon.intersection (index_geom)如果intersection.equals (index_geom):result.add(指数,,“多边形空”))队列= add_children(队列、访问、索引)elif“空”intersection.to_wkt ():result.add(指数,真正的intersection.to_wkt ()))队列= add_children(队列、访问、索引)visited.add(索引)访问= []返回结果

这段代码非常类似于原始的边界框的方法,我们只做了一些微小的变化,确保我们不是复制部分代码;因此,我们孤立add_children辅助方法。

马赛克多边形表示基准——运行时在几秒钟内
图阿

执行相同的数据生成基准我们为我们所做的边界框多边形表示。我们发现一个共同点与原方法分辨率低于100米导致多边形的代表。然而,在这种情况下,我们能够生成数据多达10万个多边形10米的分辨率,获得运行时的数据生成过程太缓慢,被认为是生产工作负载。

在100的分辨率,我们有一些非常不错的效果;花了大约600秒的数据集生成并写出100万多边形。作为参考,花了大约300秒做同样的边界框的方法。边界框是一个简单的过程,我们添加一些处理时间在数据准备阶段。我们可以证明这些投资吗?

马赛克是相当(快!)

我们已经运行相同的基准脉冲连接使用我们的马赛克数据。我们改编加入逻辑略以确保我们的边境设置和核心指标都是利用正确和最有效的方式。

def run_polyfill_chipping_join (polygons_path points_path):多边形=spark.read.format(“δ”).load (polygons_path)多边形=polygons.select (F.col (" id "),F.explode (F.col (“bng_set”)) .alias (“bng”))。选择(F.col (" id "),F.col (“bng *”。))正确的=spark.read.format(“δ”).load (right_path)返回polygons.join (正确的,=[" bng "),如何=“内心”)。在哪里(~F.col (“is_dirty”)|pip_filter (“wkt_chip”、“经常”、“北航”))#运行一个行动执行加入run_polyfill_chipping_join (polygons_path points_path)。()

is_dirty列是由我们polyfill方法引入。任何触及边境的原始几何指数将标记为脏(例如,is_dirty = True)。这些指标要求后过滤,以便正确地确定任意点,落入指数比较中包含的几何表示。这是至关重要的is_dirty过滤发生之前pip_fiter逻辑运算符调用,因为在火花短路能力;如果第一部分的逻辑表达式是正确的,第二部分将不会执行。

指向多边形镶嵌连接
图P

这段代码将产生一个更有效的执行计划的火花。由于索引空间更好的表现,我们加入表面要小得多。此外,我们post-filters受益于2集表示和马赛克几何图形的分割。

指向多边形镶嵌加入基准——运行时在几秒钟内
图问

我们终于可以量化我们的努力。PIP类型加入1000万点和100万个多边形之间通过我们新的马赛克方法已经在37秒内执行。把这个到上下文中,等效边界框连接在同一索引决议执行2549秒。这导致69 x改善运行时。

这种改进单纯侧重于运行时服务。如果我们包括准备时间,600秒的镶嵌方法,317秒的边界框的方法,我们有总调整性能提高4.5倍。

这些改进的总潜力很大程度上取决于你有多经常更新你的几何数据和多久你查询它。

通用的方法

在这篇文章中,我们主要集中在点在多边形(PIP)连接使用英国国家电网(BNG)作为参考指标体系。但是,比这更一般的方法。相同的优化可以适应任何层次地理空间系统。所不同的是,芯片的形状和可用的决议。此外,相同的优化可以帮助你扩大θ之间连接两个复杂的几何图形,如大量多边形交叉连接。

我们依然关注PySpark第一种方法,有意识地避免引入任何第三方框架。我们相信,消耗我们的解决方案,确保较低的障碍主要是Python用户量身定制。

几个创意优化我们的解决方案已经证明,可以达到70倍的性能改进与最小边界框的方法预处理增加投资。

我们带来了大规模的PIP加入到执行时间域的秒,我们打开特别针对这些数据的分析功能。

免费试着砖

相关的帖子

看到所有工程的博客的帖子