Azure Databricks 到 Azure SQL DW:长文本列
Posted
技术标签:
【中文标题】Azure Databricks 到 Azure SQL DW:长文本列【英文标题】:Azure Databricks to Azure SQL DW: Long text columns 【发布时间】:2020-06-16 16:52:23 【问题描述】:我想从 Azure Databricks 笔记本环境填充 Azure SQL DW。我正在使用带有 pyspark 的内置连接器:
sdf.write \
.format("com.databricks.spark.sqldw") \
.option("forwardSparkAzureStorageCredentials", "true") \
.option("dbTable", "test_table") \
.option("url", url) \
.option("tempDir", temp_dir) \
.save()
这很好用,但是当我包含一个内容足够长的字符串列时会出错。我收到以下错误:
Py4JJavaError:调用 o1252.save 时出错。 : com.databricks.spark.sqldw.SqlDWSideException: SQL DW 无法执行连接器生成的 JDBC 查询。
基础 SQLException(s): - com.microsoft.sqlserver.jdbc.SQLServerException:HdfsBridge::recordReaderFillBuffer - 填充记录读取器缓冲区时遇到意外错误:HadoopSqlException:字符串或二进制数据将被截断。 [错误代码 = 107090] [SQLState = S0001]
据我了解,这是因为默认字符串类型是 NVARCHAR(256)。可以配置 (reference),但最大 NVARCHAR 长度为 4k 个字符。我的字符串偶尔会达到 10k 个字符。 因此,我很好奇如何将某些列导出为文本/长文本。
如果在创建表后只执行preActions
,我猜以下方法会起作用。它不是,因此它失败了。
sdf.write \
.format("com.databricks.spark.sqldw") \
.option("forwardSparkAzureStorageCredentials", "true") \
.option("dbTable", "test_table") \
.option("url", url) \
.option("tempDir", temp_dir) \
.option("preActions", "ALTER TABLE test_table ALTER COLUMN value NVARCHAR(MAX);") \
.save()
另外,postActions
是在插入数据后执行的,因此也会失败。
有什么想法吗?
【问题讨论】:
【参考方案1】:我遇到了类似的问题,并且能够使用以下选项解决它:
.option("maxStrLength",4000)
因此,在您的示例中,这将是:
sdf.write \
.format("com.databricks.spark.sqldw") \
.option("forwardSparkAzureStorageCredentials", "true") \
.option("dbTable", "test_table") \
.option("maxStrLength",4000)\
.option("url", url) \
.option("tempDir", temp_dir) \
.save()
这是documented here:
"Spark 中的 StringType 映射到 Azure Synapse 中的 NVARCHAR(maxStrLength) 类型。您可以使用 maxStrLength 为 Azure 中名为 dbTable 的表中的所有 NVARCHAR(maxStrLength) 类型列设置字符串长度突触。”
如果您的字符串超过 4k,那么您应该:
使用 NVARCHAR(MAX) 预定义表列,然后以追加模式写入表。在这种情况下,您不能使用默认的列存储索引,因此请使用 HEAP 或设置正确的索引。惰性堆是:
CREATE TABLE example.table
(
NormalColumn NVARCHAR(256),
LongColumn NVARCHAR(4000),
VeryLongColumn NVARCHAR(MAX)
)
WITH (HEAP)
然后你可以像往常一样写它,没有 maxStrLength 选项。这也意味着您不会过度指定所有其他字符串列。
其他选项是:
-
使用 split 将 1 列转换为多个字符串列。
另存为镶木地板,然后从突触内部加载
【讨论】:
其实在大多数情况下VARCHAR(4000) 会比NVARCHAR(4000) 好,只是主题不同。以上是关于Azure Databricks 到 Azure SQL DW:长文本列的主要内容,如果未能解决你的问题,请参考以下文章
使用 azure databricks 读取 azure databricks 日志 json 文件
使用 /mnt/ 将数据从 Azure Blob 存储读取到 Azure Databricks
作业终止后如何将生成的文件从 Azure Databricks 导出到 Azure DevOps?