Azure Databricks в Azure SQL DW: длинные текстовые столбцы
Я хочу заполнить Azure SQL DW из среды записной книжки Azure Databricks. Я использую встроенный коннектор с 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: - com.microsoft.sqlserver.jdbc.SQLServerException: HdfsBridge::recordReaderFillBuffer - Возникла непредвиденная ошибка при заполнении буфера чтения записей: HadoopSqlException: строка или двоичные данные будут усечены. [ErrorCode = 107090] [SQLState = S0001]
Насколько я понимаю, это потому, что тип строки по умолчанию - NVARCHAR(256). Возможна настройка (ссылка), но максимальная длина NVARCHAR составляет 4k символов. Мои строки иногда достигают 10 тысяч символов. Поэтому мне любопытно, как я могу вместо этого экспортировать определенные столбцы как текст / длинный текст.
Я бы предположил, что следующее сработает, если бы только 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
выполняются после вставки данных, и поэтому это также не сработает.
Есть идеи?
0 ответов
У меня была аналогичная проблема, и я смог решить ее, используя следующие параметры:
.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()
Это описано здесь:
"StringType в Spark сопоставляется с типом NVARCHAR(maxStrLength) в Azure Synapse. Вы можете использовать maxStrLength, чтобы установить длину строки для всех столбцов типа NVARCHAR(maxStrLength), которые находятся в таблице с именем dbTable в Azure Synapse".
Если ваши струны превышают 4К, вам следует:
Предварительно определите столбец таблицы с помощью NVARCHAR(MAX), а затем напишите в режиме добавления в таблицу. В этом случае вы не можете использовать индекс columnstore по умолчанию, поэтому либо используйте HEAP, либо установите правильные индексы. Ленивая куча будет:
CREATE TABLE example.table
(
NormalColumn NVARCHAR(256),
LongColumn NVARCHAR(4000),
VeryLongColumn NVARCHAR(MAX)
)
WITH (HEAP)
Затем вы можете писать в него как обычно, без параметра maxStrLength. Это также означает, что вы не переопределяете все остальные строковые столбцы.
Другие варианты:
- используйте split для преобразования 1 столбца в несколько столбцов строк.
- сохранить как паркет, а затем загрузить изнутри синапса