Spark union 列顺序

Spark union column order

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

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|
+----+----+

看起来好像使用了 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)

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

Spark 联合是根据标准 SQL 实现的,因此按位置解析列。 API documentation:

也说明了这一点

Return a new DataFrame containing union of rows in this and another frame.

This is equivalent to UNION ALL in SQL. To do a SQL-style set union (that does >deduplication of elements), use this function followed by a distinct.

Also as standard in SQL, this function resolves columns by position (not by name).

因为 Spark >= 2.3 你可以使用 unionByName 联合两个数据帧,列名得到解析。