使用Sedona创建带geometry列的Iceberg表时遇错求助
问题:创建带Geometry列的Iceberg表失败,报错“User-defined types are not supported”
我尝试用以下代码创建包含geometry列的Iceberg表:
import org.apache.sedona.sql.utils.SedonaSQLRegistrator SedonaSQLRegistrator.registerAll(spark) val stmt = """ CREATE TABLE local.myschema.geotable (id string, geom geometry) USING iceberg TBLPROPERTIES('format-version'='3'); """ spark.sql(stmt).show()
但执行后出现如下错误:
25/04/06 16:59:18 WARN UDTRegistration: Cannot register UDT for org.geotools.coverage.grid.GridCoverage2D, which is already registered. 25/04/06 16:59:18 WARN SimpleFunctionRegistry: The function rs_union_aggr replaced a previously registered function. 25/04/06 16:59:18 WARN UDTRegistration: Cannot register UDT for org.locationtech.jts.geom.Geometry, which is already registered. 25/04/06 16:59:18 WARN UDTRegistration: Cannot register UDT for org.apache.sedona.common.geometryObjects.Geography, which is already registered. 25/04/06 16:59:18 WARN UDTRegistration: Cannot register UDT for org.locationtech.jts.index.SpatialIndex, which is already registered. 25/04/06 16:59:18 WARN SimpleFunctionRegistry: The function st_envelope_aggr replaced a previously registered function. 25/04/06 16:59:18 WARN SimpleFunctionRegistry: The function st_intersection_aggr replaced a previously registered function. 25/04/06 16:59:18 WARN SimpleFunctionRegistry: The function st_union_aggr replaced a previously registered function. java.lang.UnsupportedOperationException: User-defined types are not supported at org.apache.iceberg.spark.SparkTypeVisitor.visit(SparkTypeVisitor.java:52) at org.apache.iceberg.spark.SparkTypeVisitor.visit(SparkTypeVisitor.java:37) at org.apache.iceberg.spark.SparkSchemaUtil.convert(SparkSchemaUtil.java:126) at org.apache.iceberg.spark.SparkCatalog.createTable(SparkCatalog.java:238) at org.apache.spark.sql.connector.catalog.TableCatalog.createTable(TableCatalog.java:223)
我使用以下命令启动spark-shell:
spark-shell \ --conf spark.serializer=org.apache.spark.serializer.KryoSerializer \ --conf spark.kryo.registrator=org.apache.sedona.core.serde.SedonaKryoRegistrator \ --conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions,org.apache.sedona.sql.SedonaSqlExtensions \ --conf spark.sql.catalog.local=org.apache.iceberg.spark.SparkCatalog \ --conf spark.sql.catalog.local.type=hadoop \ --conf spark.sql.catalog.local.warehouse=file:///Users/stefan/tmp/lakehouse \ --packages org.apache.sedona:sedona-spark-shaded-3.5_2.12:1.7.1,org.datasyslab:geotools-wrapper:1.7.1-28.5,org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:1.8.1
请问问题出在哪里?是否需要使用某些库的快照版本?
解答
核心问题原因
Iceberg 1.8.1版本默认不支持Spark的用户自定义类型(UDT),而Sedona的geometry类型本质是基于JTS Geometry实现的UDT,直接在Iceberg表中声明该类型会触发类型转换失败。
解决方案
方案1:用Iceberg支持的类型存储几何数据,通过Sedona函数转换
将几何数据以WKB/WKT格式的字符串或二进制类型存储,读写时通过Sedona的转换函数处理:
创建表时改用二进制类型:
val stmt = """ CREATE TABLE local.myschema.geotable (id string, geom_wkb binary) USING iceberg TBLPROPERTIES('format-version'='3'); """
写入数据时转成WKB格式:
spark.sql("INSERT INTO local.myschema.geotable SELECT id, ST_AsWKB(geom) FROM source_table")
读取数据时恢复为Geometry类型:
spark.sql("SELECT id, ST_GeomFromWKB(geom_wkb) AS geom FROM local.myschema.geotable")
方案2:升级Iceberg到支持UDT的版本
Iceberg从2.0.0版本开始正式支持Spark UDT,你可以升级Iceberg版本到2.0.0或更高,同时确保Sedona版本与Spark兼容:
修改spark-shell启动命令中的Iceberg包版本:
--packages org.apache.sedona:sedona-spark-shaded-3.5_2.12:1.7.1,org.datasyslab:geotools-wrapper:1.7.1-28.5,org.apache.iceberg:iceberg-spark-runtime-3.5_2.12:2.0.0
升级后即可直接用geometry类型创建Iceberg表,无需额外转换。
额外注意事项
- 启动命令中
spark.sql.extensions的顺序不影响核心功能,但建议保持Iceberg扩展在前。 - 优先使用正式发布的2.0.0+版本,稳定性比快照版本更有保障。
内容的提问来源于stack exchange,提问作者Stefan Ziegler
相关产品推荐
相关产品推荐

