我自己也深入研究了一下这个问题,我想知道你对我的解决方法/POC的看法。请参阅https://github.com/ravwojdyla/spark-schema-utils。它可以转换表达式并更新属性。
假设我有两个模式,第一个没有任何元数据,我们称其为schema_wo_metadata
:
{
"fields": [
{
"metadata": {},
"name": "oa",
"nullable": false,
"type": {
"containsNull": true,
"elementType": {
"fields": [
{
"metadata": {},
"name": "ia",
"nullable": false,
"type": "long"
},
{
"metadata": {},
"name": "ib",
"nullable": false,
"type": "string"
}
],
"type": "struct"
},
"type": "array"
}
},
{
"metadata": {},
"name": "ob",
"nullable": false,
"type": "double"
}
],
"type": "struct"
}
第二个有额外元数据的,内部(ia
)和外部(ob
)都有,我们称之为schema_wi_metadata
{
"fields": [
{
"metadata": {},
"name": "oa",
"nullable": false,
"type": {
"containsNull": true,
"elementType": {
"fields": [
{
"metadata": {
"description": "this is ia desc"
},
"name": "ia",
"nullable": false,
"type": "long"
},
{
"metadata": {},
"name": "ib",
"nullable": false,
"type": "string"
}
],
"type": "struct"
},
"type": "array"
}
},
{
"metadata": {
"description": "this is ob desc"
},
"name": "ob",
"nullable": false,
"type": "double"
}
],
"type": "struct"
}
现在假设我有一个具有schema_wo_metadata
模式的数据集,并希望将模式与schema_wi_metadata
交换:
from pyspark.sql import SparkSession
from pyspark.sql import Row, DataFrame
from pyspark.sql.types import StructType
schema_wo_metadata: StructType = ...
schema_wi_metadata: StructType = ...
spark = SparkSession.builder \
.config("spark.jars.packages", "io.github.ravwojdyla:spark-schema-utils_2.12:0.1.0") \
.getOrCreate()
df = spark.createDataFrame(data=[Row(oa=[Row(ia=0, ib=1)], ob=3.14),
Row(oa=[Row(ia=2, ib=3)], ob=42.0)],
schema=schema_wo_metadata)
_jdf = spark._sc._jvm.io.github.ravwojdyla.SchemaUtils.update(df._jdf, schema.json())
new_df = DataFrame(_jdf, df.sql_ctx)
现在,new_df
包含了schema_wi_metadata
,例如:
new_df.schema["oa"].dataType.elementType["ia"].metadata
有什么意见吗?
cast
/struct
或构建select
语句等方法。我知道我的模式是兼容的,并且我想知道是否可以进行“零成本”模式交换。 - ravselect
触发的任何计算都不会增加额外的Spark阶段,因此在所有实际目的下,您可以安全地忽略它们。根据select
之前的转换,可能需要在之前添加一个额外的cache。 - wernerselect
表達式,但我寧願避免編寫這樣的查詢生成器。支持任意模式(嵌套和元數據:可為空、說明和任意字段)可能需要相當多的工作。 - rav