文章目录

  • Apache Sedona(GeoSpark) Spatial Join
  • Range join
  • Distance join
  • 源码解析
    • SedonSQLRegistrator.registerAll(sparkSession)
    • JoinQueryDetector
      • planSpatialJoin
      • planDistanceJoin
    • TraitJoinQueryExec
      • doExecute
        • 1. 构造SpatialRDD
        • 2. doSpatialPartitioning
        • 3. spatialJoin
        • 4. extraCondition and JoinRow

Apache Sedona(GeoSpark) Spatial Join

Sedona Spatial operators fully supports Apache SparkSQL query optimizer. It has the following query optimization features:

  • Automatically optimizes range join query and distance join query.
  • Automatically performs predicate pushdown.

Range join

Introduction: Find geometries from A and geometries from B such that each geometry pair satisfies a certain predicate. Most predicates supported by SedonaSQL can trigger a range join.

Spark SQL Example:

SELECT *
FROM polygondf, pointdf
WHERE ST_Contains(polygondf.polygonshape,pointdf.pointshape)
SELECT *
FROM polygondf, pointdf
WHERE ST_Intersects(polygondf.polygonshape,pointdf.pointshape)
SELECT *
FROM pointdf, polygondf
WHERE ST_Within(pointdf.pointshape, polygondf.polygonshape)

Spark SQL Physical plan:

== Physical Plan ==
RangeJoin polygonshape#20: geometry, pointshape#43: geometry, false
:- Project [st_polygonfromenvelope(cast(_c0#0 as decimal(24,20)), cast(_c1#1 as decimal(24,20)), cast(_c2#2 as decimal(24,20)), cast(_c3#3 as decimal(24,20)), mypolygonid) AS polygonshape#20]
:  +- *FileScan csv
+- Project [st_point(cast(_c0#31 as decimal(24,20)), cast(_c1#32 as decimal(24,20)), myPointId) AS pointshape#43]+- *FileScan csv

!!!note
All join queries in SedonaSQL are inner joins

Distance join

Introduction: Find geometries from A and geometries from B such that the internal Euclidean distance of each geometry pair is less or equal than a certain distance

Spark SQL Example:

Only consider fully within a certain distance

SELECT *
FROM pointdf1, pointdf2
WHERE ST_Distance(pointdf1.pointshape1,pointdf2.pointshape2) < 2

Consider intersects within a certain distance

SELECT *
FROM pointdf1, pointdf2
WHERE ST_Distance(pointdf1.pointshape1,pointdf2.pointshape2) <= 2

Spark SQL Physical plan:

== Physical Plan ==
DistanceJoin pointshape1#12: geometry, pointshape2#33: geometry, 2.0, true
:- Project [st_point(cast(_c0#0 as decimal(24,20)), cast(_c1#1 as decimal(24,20)), myPointId) AS pointshape1#12]
:  +- *FileScan csv
+- Project [st_point(cast(_c0#21 as decimal(24,20)), cast(_c1#22 as decimal(24,20)), myPointId) AS pointshape2#33]+- *FileScan csv

!!!warning
Sedona doesn’t control the distance’s unit (degree or meter). It is same with the geometry. To change the geometry’s unit, please transform the coordinate reference system. See ST_Transform.

源码解析

SedonSQLRegistrator.registerAll(sparkSession)

在初始化SparkSession后,需要调用SedonaSQLRegistrator.registerAll(sparkSession)来注册SedonaSQL User Defined Type, User Defined Function and optimized join query strategy。

JoinQueryDetector是针对spatial join的策略,UdtRegistrator.registerAll()注册GeometryUDT和IndexUDT。UdfRegistrator.registerAll(sqlContext)注册自定义的udf,udaf等。

JoinQueryDetector



JoinQueryDetector继承自Strategy,用于将逻辑计划转换为物理计划。从apply方法中可以看到,JoinQueryDetector匹配Join逻辑计划节点,根据其Join类中的condition的类型来决定生成那种join类型,即RangeJoinExec或者DistanceJoinExec,并传入leftShape和rightShape这两个表示几何列的表达式。

Spark Join 逻辑计划:

planSpatialJoin


此方法用于生成RangeJoinExec物理计划。首先调用matchExpressionsToPlans检查left和right两个子逻辑计划的outputSet是否包含了Expression代表的几何类型。

planDistanceJoin


此方法用于生成DistanceJoinExec,具体逻辑与planSpatialJoin大致相同。

TraitJoinQueryExec

RangeJoinExec :

DistanceJoinExec :

可以看出DistanceJoinExec和RangeJoinExec的具体实现逻辑都在TraitJoinQueryExec中。

TraitJoinQueryExec :

TraitJoinQueryExec是一个接口,继承SparkPlan。

doExecute

1. 构造SpatialRDD


在doExecute方法中首先调用BindReferences.bindReference方法,将leftShape和rightShape绑定到left和right子物理计划的output中。生成的BindReferences表达式的eval方法可以从left和right的InternalRow中直接获取到几何列。

然后调用left和right的execute方法获取子RDD。然后调用toSpatialRddPair方法生成SpatialRdd(这里不介绍SpatialRdd的内部结构了),即从unsafeRow中获取到几何列,然后转换为Geometry对象。


toSpatialRdd方法利用 内部自定义的集合对象序列化器GeometrySerializer.deserialize方法将获取到的几何列转换对集合对象。

2. doSpatialPartitioning


为了完成spatial join,两个SpatialRDD必须具有相同的分区。首先决定JoinSparitionDominantSide,然后决定numPartitions。

doSpatialPartitioning方法中,dominantShapes根据sedonaConf的设置选择相应的空间分区的方式进行自定义分区。followerShapes获取dominantShapes的分区器,进行相同的空间分区。

3. spatialJoin

首先构造JoinParams对象,其决定了join时是否使用索引,是否考虑边界相交、索引类型,以及joinBuildSide。

然后调用JoinQuery.spatialJoin方法,进行空间连接操作。

JoinQuery.spatialJoin


首先检查两个SpatialRDD的CRS和Partitioning是否相符合。

构造JoinJudgement,其继承自FlatMapFunction2接口,用于zipPartitions算子中,两个SpatialRDD中相同分区上的元素如何进行空间连接。

比如:

  • RightIndexLookupJudgement :leftRDD.spatialPartitionedRDD.zipPartitions(rightRDD.indexedRDD, judgement),即利用rightRDD.indexedRDD上的分区空间索引,逐个遍历leftRDD.spatialPartitionedRDD中的记录,对空间索引进行查询,获取可以空间连接的记录对。

  • DynamicIndexLookupJudgement需要在连接之前进行分区索引的建立。

4. extraCondition and JoinRow


最后senoda支持对join后过滤的谓词下推,所以可以进行定义extraCondition进行过滤。

然后由于上面进行空间连接的两个表中几何列,而我们要获得的是表中所有列的连接。之前我们将Row对象设置到了Geometry中的userData中,所以利用getUserData方法获取UnsafeRow,然后构造UnsafeRowJoiner,将两个UnsafeRow进行连接后返回。

Apache Sedona(GeoSpark) spatial join 源码解析相关推荐

  1. StarRocks Join Reorder 源码解析

    导读:欢迎来到 StarRocks 源码解析系列文章,我们将为你全方位揭晓 StarRocks 背后的技术原理和实践细节,助你逐步了解这款明星开源数据库产品. 本期 StarRocks 技术内幕将介绍 ...

  2. LRU算法,以及Apache LRUMap源码解析

    1. 什么是LRU LRU(least recently used) : 最近最少使用 LRU就是一种经典的算法,在容器中,对元素定义一个最后使用时间,当新的元素写入的时候,如果容器已满,则淘汰最近最 ...

  3. Apache IoTDB源码解析(0.11.2版本):Session的源码解析

    1. 声明 当前内容主要为解析Apache IoTDB 0.11.2版本的Session的源码解析 通过前面的Apache Thrift的Demo,可以发现iotdb中的server是使用了thrif ...

  4. Apache Kafka-Spring Kafka生产消费@KafkaListener源码解析

    文章目录 概述 Spring-kafka生产者源码流程 Spring-kafka消费者源码流程(`@EnableKafka`和`@KafkaListener` ) Flow KafkaListener ...

  5. python flask源码解析_用尽洪荒之力学习Flask源码

    [TOC] 一直想做源码阅读这件事,总感觉难度太高时间太少,可望不可见.最近正好时间充裕,决定试试做一下,并记录一下学习心得. 首先说明一下,本文研究的Flask版本是0.12. 首先做个小示例,在p ...

  6. Flink 全网最全资源(视频、博客、PPT、入门、原理、实战、性能调优、源码解析、问答等持续更新)

    Flink 学习 https://github.com/zhisheng17/flink-learning 麻烦路过的各位亲给这个项目点个 star,太不易了,写了这么多,算是对我坚持下来的一种鼓励吧 ...

  7. JVM SandBox源码解析(一):启动时初始化、启动时加载模块、ModuleHttpServlet进行Http路由

    前言 上篇JVM SandBox实现原理详解文章中,主要解析了JVM SandBox的核心实现原理,并且对SandBoxClassLoader和ModuleClassLoader做了源码解析,也解释了 ...

  8. Dubbo源码解析-Dubbo服务消费者_Dubbo协议(一)

    前言: 在介绍完Dubbo 本地模式(Injvm协议)下的服务提供与消费后,上文我们又介绍了Dubbo远程模式(dubbo协议)下的服务暴露过程,本质上就是通过Netty将dubbo协议端口暴露出去, ...

  9. netty4.0源码解析(持续更新)

    文章目录 netty 1:环境配置 与其他对比 future缺陷 2:结构 3:设计模式 delay 策略模式 todo 责任链模式 todo 单例模式模式 todo 装饰者模式 ReplayingD ...

最新文章

  1. Qt中的QGridLayout
  2. 正则表达式学习 (一) 转
  3. cfg桩设备型号_什么是CFG桩?带您看下CFG桩施工工艺及流程,检测项目
  4. 清空邮件队列中的邮件
  5. php限制只能中文,php如何实现一个账号只能有一个人登录
  6. 年薪50万的程序员_985程序员年薪50万,看似风光,但当事人却想转行
  7. 理想的正方形 HAOI2007(二维RMQ)
  8. linux下使用John检测用户是否存在弱口令
  9. php-5.6 安装部署整理
  10. 软考项目管理师考试随笔
  11. 学生选课管理系统php,学生选课管理系统(全源代码.doc
  12. Directx8 学习笔记
  13. 【在线课件制作软件】Focusky教程 | 导出PDF并打印
  14. python划分有限元网格_有限元分析网格划分的步骤和类型
  15. 2万字硬核剖析网页自定义字体解析(css样式表解析、字体点阵图绘制与本地图像识别等)...
  16. Rhino导入Revit生成体量幕墙的方法和操作要点
  17. 【Transformer】李沐论文逐段精读学习笔记
  18. 2021-10-12 Java 中 Filed.modifiers 之 java.lang.reflect.Modifier
  19. ktt算法 约化_深度学习面试题
  20. java如何判断回文数

热门文章

  1. Corel Painter 2020 for Mac(绘图软件)
  2. python快速编程入门课本中的名片管理器_基于python实现名片管理系统
  3. mplayer-php,Mplayer使用及快捷键
  4. 常见的k临近向量检索算法
  5. 5分钟给意志力加油--自控力
  6. 自建Kubernetes的LoadBalancer类型服务方案-MetalLB
  7. 【视频编码学习】——SAD和SATD
  8. 阿狸给桃子的999封情书(123封)
  9. 游戏本天梯_实况足球手游国服5月天梯胜率榜+极品补丁一枚
  10. 大数据解读 | B站2020跨年晚会如何看哭我们?