Spark写入Azure Synapse数据库时,指定长度为8000的Varbinary列触发UNSUPPORTED_DATATYPE错误
Spark写入Azure Synapse数据库时,指定长度为8000的Varbinary列触发UNSUPPORTED_DATATYPE错误
看起来你遇到的是Spark SQL Server JDBC驱动对带长度的VARBINARY(8000)类型解析不兼容的问题,同时你还需要确保创建的是Synapse默认的聚集列存储索引(CCI)表而非堆表,我给你两个实用的解决思路:
思路一:先建基础表再调整列长度,同时指定CCI选项
这个方法分两步操作,先通过Spark JDBC创建包含无长度限制VARBINARY的表(避开驱动解析问题),同时设置建表参数确保生成CCI表,之后再用DDL语句修改列长度到8000:
- 调整写入代码,新增CCI建表选项:
ds.write() .format(FORMAT_JDBC) .option("url", JDBC_URL) .option("user", USER_VALUE) .option("password", PASSWORD_VALUE) .option(DRIVER_CLASS_NAME, "com.microsoft.sqlserver.jdbc.SQLServerDriver") .option(DB_TABLE, "\"ImageStore\"") .option("createTableColumnTypes","ImageName varchar(8000),ImageData VARBINARY") .option("createTableOptions", "WITH (CLUSTERED COLUMNSTORE INDEX)") // 强制创建CCI表 .mode(SaveMode.Overwrite) .save();
- 执行ALTER语句修改列长度:
// 通过临时视图执行DDL String alterSql = "ALTER TABLE ImageStore ALTER COLUMN ImageData VARBINARY(8000)"; spark.sql("CREATE OR REPLACE TEMPORARY VIEW dummy AS SELECT 1 AS id"); dummy.write() .format(FORMAT_JDBC) .option("url", JDBC_URL) .option("user", USER_VALUE) .option("password", PASSWORD_VALUE) .option(DRIVER_CLASS_NAME, "com.microsoft.sqlserver.jdbc.SQLServerDriver") .option("dbtable", s"($alterSql) AS alter_table") .mode(SaveMode.Ignore) .save();
思路二:直接用DDL创建表,再写入数据
这种方式完全自定义表结构,从根源上避开驱动的类型解析问题:
- 先执行建表DDL:
String createTableSql = "CREATE TABLE ImageStore (" + "ImageName varchar(8000)," + "ImageData VARBINARY(8000)" + ") WITH (CLUSTERED COLUMNSTORE INDEX)"; spark.sql("CREATE OR REPLACE TEMPORARY VIEW dummy AS SELECT 1 AS id"); dummy.write() .format(FORMAT_JDBC) .option("url", JDBC_URL) .option("user", USER_VALUE) .option("password", PASSWORD_VALUE) .option(DRIVER_CLASS_NAME, "com.microsoft.sqlserver.jdbc.SQLServerDriver") .option("dbtable", s"($createTableSql) AS create_table") .mode(SaveMode.Ignore) .save();
- 写入数据(此时无需指定
createTableColumnTypes,表结构已定义好):
ds.write() .format(FORMAT_JDBC) .option("url", JDBC_URL) .option("user", USER_VALUE) .option("password", PASSWORD_VALUE) .option(DRIVER_CLASS_NAME, "com.microsoft.sqlserver.jdbc.SQLServerDriver") .option(DB_TABLE, "\"ImageStore\"") .mode(SaveMode.Overwrite) .save();
这两种方案都能满足你的需求:创建新的CCI表、指定VARBINARY(8000)列,同时避开Spark JDBC驱动的类型解析错误。
备注:内容来源于stack exchange,提问作者Nitish Sharma
相关产品推荐
相关产品推荐

