5

我想从 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)。可以配置(参考),但最大 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在插入数据后执行,因此这也会失败。

有任何想法吗?

4

1 回答 1

3

我遇到了类似的问题,并且能够使用以下选项解决它:

.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()

记录在这里

“Spark 中的 StringType 映射到 Azure Synapse 中的 NVARCHAR(maxStrLength) 类型。您可以使用 maxStrLength 为 Azure Synapse 中名为 dbTable 的表中的所有 NVARCHAR(maxStrLength) 类型列设置字符串长度。”

如果您的琴弦超过 4k,那么您应该:

使用 NVARCHAR(MAX) 预定义表列,然后以附加模式写入表。在这种情况下,您不能使用默认的列存储索引,因此请使用 HEAP 或设置正确的索引。惰性堆将是:

CREATE TABLE example.table
(
    NormalColumn NVARCHAR(256),
    LongColumn NVARCHAR(4000),
    VeryLongColumn NVARCHAR(MAX)
) 
WITH (HEAP)

然后你可以像往常一样写它,没有 maxStrLength 选项。这也意味着您不会过度指定所有其他字符串列。

其他选择是:

  1. 使用 split 将 1 列转换为多个字符串列。
  2. 另存为镶木地板,然后从突触内部加载
于 2020-09-09T16:35:29.673 回答