You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 12:03:26