我的火花任务的性能有问题。
我有两个表:
geo渔网。大小约为200万行。架构:
cell_id minlat minlon maxlat maxlon
geo对象。大小约20万行。架构:
objid lat lon
我想要的是加入这些表并找到每个对象的单元格。所需架构:
objid lat lon cell_id
第一个天真的解决方案是:
cellDF.join(objDF, callUDF("isContain", col("minlat"),..col("lat"), col("lon")));
UDF仅检查minlat <= lat <= maxlat && minlon <= lon <= maxlon
但是此解决方案工作非常缓慢。在拥有20多个节点的群集上要花费几个小时。
我尝试的第二件事-使用esri-geometry-api。我为每个单元格创建了Polygon
,为每个对象创建了Point
,并选中了polygon.contains(point)
。
但是这种解决方案的工作速度比第一种慢。
对于这种类似的连接,也许有“最佳实践”?我找到了有关QuadTree的一些信息,但是在spark中找不到该算法的任何清晰的文档和示例。
P.S。 Spark版本是2.2.0。
答案 0 :(得分:1)
假设您有两个csv文件(如果不是,则只需更改输入即可)
// Create a spark session
SparkSession session = SparkSession.builder().appName("name here").getOrCreate();
// Create datasets for both input
Dataset<Fishnet> fishnet = session.read().format("csv").option("header", true).option("inferSchema", true).load("fishnet.csv").as(Encoders.bean(Fishnet.class));
Dataset<GeoObject> geoObject = session.read().format("csv").option("header", true).option("inferSchema", true).load("geoObject.csv").as(Encoders.bean(GeoObject.class));
// Create temp view on datasets
fishnet.createOrReplaceTempView("fishnet");
geoObject.createOrReplaceTempView("geoObject");
// Now create a query to retrieve the result [objid lat lon cell_id]
Dataset<Row> result = session.sql("select objid, lat, lon, cell_id from fishnet, geoObject where lat >= minlat and lat <= maxlat and lon >= minlon and lon <= maxlon");