Java Spark:将数据集的两列合并为一列
我有一个ID为2个不同列的表。我有另一个表,其中包含与ID关联的对象。我想从表2中筛选出id存在于表1的id1或id2中的id 表1:Java Spark:将数据集的两列合并为一列,java,scala,apache-spark,Java,Scala,Apache Spark,我有一个ID为2个不同列的表。我有另一个表,其中包含与ID关联的对象。我想从表2中筛选出id存在于表1的id1或id2中的id 表1: | id1 | id2 | | 1 | 1 | | 1 | 1 | | 1 | 3 | | 2 | 5 | | 3 | 1 | | 3 | 2 | | 3 | 3 | 表2: | id | obj | | 1 | 'A' | | 2 | 'B' | | 3 |
| id1 | id2 |
| 1 | 1 |
| 1 | 1 |
| 1 | 3 |
| 2 | 5 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
表2:
| id | obj |
| 1 | 'A' |
| 2 | 'B' |
| 3 | 'C' |
| 4 | 'D' |
| 5 | 'E' |
| 6 | 'F' |
| 7 | 'G' |
我的想法是从表1中创建一个包含唯一ID的列表,该ID将是上面示例中的[1,2,3,5]
然后根据列表过滤出数据帧,并给出结果
| id | obj |
| 1 | 'A' |
| 2 | 'B' |
| 3 | 'C' |
| 5 | 'E' |
尽管我对解决方案的可伸缩性表示担忧。列表可能很大,在某些情况下甚至可能无法加载到内存中。在这种情况下有什么建议吗
谢谢。使用spark SQL-注意-spark中的连接包含一整套性能注意事项,包括DF大小、密钥分配等。因此,请您熟悉 一般来说,尽管:
table2.as("t2")
.join(
table1.as("t1"),
$"t2.id" === $"t1.id1" || $"t2.id" === $"t1.id2",
"left"
)
.where($"t1.id1".isNull)
.select("t2.*")
另一种方法:
val id_table = table1.select(explode(array('*)).as("id")).distinct()
val result = table2.join(id_table,"id")
result.show()
输出:
+---+---+
| id|obj|
+---+---+
| 1|'A'|
| 2|'B'|
| 3|'C'|
| 5|'E'|
+---+---+
以下方法可行
import spark.implicits._
val t1 = Seq((1,1),(1,1),(1,3),(2,5),(3,1),(3,2),(3,3))
val t2 = Seq((1,"A"),(2,"B"),(3,"C"),(4,"D"),(5,"E"),(6,"F"),(7,"G"))
val tt1 = sc.parallelize(t1).toDF("id1","id2")
.persist(StorageLevel.MEMORY_AND_DISK)
val tt2 = sc.parallelize(t2).toDF("id", "obj")
.persist(StorageLevel.MEMORY_AND_DISK)
tt1.show()
tt2.show()
tt1.createOrReplaceTempView("table1")
tt2.createOrReplaceTempView("table2")
val output = sqlContext.sql(
"""
|SELECT DISTINCT id, obj
|FROM table1 t1
|JOIN table2 t2 ON(t1.id1 = t2.id) OR (t1.id2 = id)
|ORDER BY id
|""".stripMargin).persist(StorageLevel.MEMORY_AND_DISK)
output.show()
输出
+---+---+
| id|obj|
+---+---+
| 1| A|
| 2| B|
| 3| C|
| 5| E|
+---+---+
对于内存问题,您可以将数据持久化到内存和磁盘,但是还有更多选项,您可以选择适合您特定问题的最佳选项,您可以按照以下链接进行操作:
<>我会考虑配置分区的数量:
spark.sql.shuffle.partitions
/*
Configures the number of partitions to use when shuffling data for joins or aggregations.
*/
val spark = SparkSession
.builder()
.appName("MySparkProcess")
.master("local[*]")
.config("spark.sql.shuffle.partitions","400") //Change to a more reasonable default number of partitions for our data
.config("spark.app.id","MySparkProcess") // To silence Metrics warning
.getOrCreate()
我也会查看此链接以了解进一步的配置:
我希望这有帮助