Spark联合列顺序

Cha*_* Du 26 apache-spark apache-spark-sql pyspark pyspark-sql

我最近在 Spark 中遇到了一些奇怪的事情。据我了解,鉴于spark dfs的基于列的存储方法,列的顺序确实没有任何意义,它们就像字典中的键。

在 a 期间df.union(df2),列的顺序重要吗?我会假设它不应该,但根据 sql 论坛的智慧,它确实如此。

所以我们有 df1

df1
|  a|   b|
+---+----+
|  1| asd|
|  2|asda|
|  3| f1f|
+---+----+

df2
|   b|  a|
+----+---+
| asd|  1|
|asda|  2|
| f1f|  3|
+----+---+

result
|   a|   b|
+----+----+
|   1| asd|
|   2|asda|
|   3| f1f|
| asd|   1|
|asda|   2|
| f1f|   3|
+----+----+

Run Code Online (Sandbox Code Playgroud)

看起来使用了 df1 中的架构,但数据似乎已按照其原始数据帧的顺序加入。显然,解决方案是这样做df1.union(df2.select(df1.columns))

但主要问题是,它为什么要这样做?仅仅是因为它是 pyspark.sql 的一部分,还是 Spark 中有一些我在理解上搞砸了的底层数据架构?

如果有人想尝试创建测试集的代码

d1={'a':[1,2,3], 'b':['asd','asda','f1f']}
d2={ 'b':['asd','asda','f1f'], 'a':[1,2,3],}
pdf1=pd.DataFrame(d1)
pdf2=pd.DataFrame(d2)
df1=spark.createDataFrame(pdf1)
df2=spark.createDataFrame(pdf2)
test=df1.union(df2)
Run Code Online (Sandbox Code Playgroud)

cro*_*oik 37

Spark 联合是根据标准 SQL 实现的,因此按位置解析列。API文档也说明了这一点:

返回一个包含此帧和另一个帧中行的联合的新 DataFrame。

这相当于 SQL 中的 UNION ALL。要执行 SQL 样式的集合联合(对元素进行 > 重复数据删除),请使用此函数后跟一个 distinct。

同样作为 SQL 中的标准,此函数按位置(而不是按名称)解析列。

由于Spark >= 2.3,您可以使用unionByName合并两个数据,因为列名得到解析。

  • 使用“unionByName”与“union”相比对性能有影响吗? (3认同)
  • 当然,因为spark之前需要检查现有的列名,但它很小([链接](https://github.com/apache/spark/blame/cee4ecbb16917fa85f02c635925e2687400aa56b/sql/core/src/main/scala/org/ apache/spark/sql/Dataset.scala#L1894))。 (3认同)
  • 此外,unionByName 显然与 unionAll 类似,因为它不会删除重复记录。 (2认同)
  • @combinatorist 这是正确的。您必须使用它,然后使用 [.distinct()](https://spark.apache.org/docs/latest/api/python/pyspark.sql.html#pyspark.sql.DataFrame.distinct) 来删除重复行。 (2认同)

小智 12

在 spark Union 中没有对列的元数据进行处理,并且数据也不会像您想象的那样乱序。相反,联合是在列号上完成的,如果您要联合 2 个 Df,则两者都必须具有相同的列数..在进行联合之前,您必须考虑列的位置。与 SQL 或 Oracle 或其他 RDBMS 不同,spark 中的底层文件是物理文件。希望这能回答你的问题