Spark JDBC для DashDB (DB2) с ошибками CLOB

Я работаю, чтобы подключить мое искровое приложение к DashDB. В настоящее время я могу загрузить свои данные очень хорошо.

Однако я не могу сохранить DataFrame в DashDB.

Любое понимание будет полезно.

  var jdbcSets = sqlContext.read.format("jdbc").options(Map("url" -> url, "driver" -> driver, "dbtable" -> "setsrankval")).load()
  jdbcSets.registerTempTable("setsOpponentRanked")
  jdbcSets = jdbcSets.coalesce(10)
  sqlContext.cacheTable("setsOpponentRanked")

Однако, когда я пытаюсь сохранить большие DataFrames, я получаю сообщение об ошибке:

Ошибка SQL DB2: SQLCODE=-1666, SQLSTATE=42613, SQLERRMC=CLOB, DRIVER=4.19.26

Код, который я использую для сохранения данных, выглядит следующим образом:

val writeproperties = new Properties()
  writeproperties.setProperty("user", "dashXXXX")
  writeproperties.setProperty("password", "XXXXXX")
  writeproperties.setProperty("rowId", "false")
  writeproperties.setProperty("driver", "com.ibm.db2.jcc.DB2Driver")
  results.write.mode(SaveMode.Overwrite).jdbc(writeurl, "players_stat_temp", writeproperties)

Пример тестового набора данных можно увидеть здесь:

println("Test set: "+results.first()) 
Test set: ['Damir DZUMHUR','test','test','test','test','test','test','test','test','test','test','test','test','test','test','test','test','test','test','test','test','test',null,null,null,null,null,null,null]

Схема DataFrame выглядит следующим образом:

    root
 |-- PLAYER: string (nullable = true)
 |-- set01: string (nullable = true)
 |-- set02: string (nullable = true)
 |-- set12: string (nullable = true)
 |-- set01weakseed: string (nullable = true)
 |-- set01medseed: string (nullable = true)
 |-- set01strongseed: string (nullable = true)
 |-- set02weakseed: string (nullable = true)
 |-- set02medseed: string (nullable = true)
 |-- set02strongseed: string (nullable = true)
 |-- set12weakseed: string (nullable = true)
 |-- set12medseed: string (nullable = true)
 |-- set12strongseed: string (nullable = true)
 |-- set01weakrank: string (nullable = true)
 |-- set01medrank: string (nullable = true)
 |-- set01strongrank: string (nullable = true)
 |-- set02weakrank: string (nullable = true)
 |-- set02medrank: string (nullable = true)
 |-- set02strongrank: string (nullable = true)
 |-- set12weakrank: string (nullable = true)
 |-- set12medrank: string (nullable = true)
 |-- set12strongrank: string (nullable = true)
 |-- minibreak: string (nullable = true)
 |-- minibreakweakseed: string (nullable = true)
 |-- minibreakmedseed: string (nullable = true)
 |-- minibreakstrongseed: string (nullable = true)
 |-- minibreakweakrank: string (nullable = true)
 |-- minibreakmedrank: string (nullable = true)
 |-- minibreakstrongrank: string (nullable = true)

Я посмотрел на jdbc DB2Dialect и увидел, что код для StringType сопоставлен с CLOB. Интересно, поможет ли следующее:

private object DB2CustomDialect extends JdbcDialect {
    override def canHandle(url: String): Boolean = url.startsWith("jdbc:db2")
    override def getJDBCType(dt: DataType): Option[JdbcType] = dt match {
            case StringType => Option(JdbcType("VARCHAR(10000)", java.sql.Types.VARCHAR))
            case BooleanType => Option(JdbcType("CHAR(1)", java.sql.Types.CHAR))
            case _ => None
    }
}

3 ответа

Хорошо работает, добавив пользовательский диалект.

JdbcDialects.registerDialect(new DB2CustomDialect())

Да, действительно, текущая реализация DB2Dialect не является оптимальной. Мы посмотрим и, вероятно, создадим запрос на извлечение, чтобы изменить отображение StringType на VARCHAR.

Я думаю, мысль о том, чтобы использовать CLOB на первом месте, заключалась в том, что это безопаснее, когда вы хотите иметь возможность хранить строки любой длины, тогда как VARCHAR ограничен максимальным размером страницы DB2/dashDB. Но я думаю, что маловероятно, что в свойствах фрейма данных будут помещаться очень длинные строки, а CLOB вызывает все виды операционных проблем, например тот факт, что он не поддерживается в таблицах COLUMN ORGANIZED в DB2, которая является типом таблицы по умолчанию в dashDB, и именно поэтому вы сталкиваетесь с проблемой при попытке записать ваш фрейм данных в dashDB. Но CLOB также проблематичен для производительности ввода-вывода в DB2, поскольку он не обязательно кэшируется в памяти базы данных, как и все другие данные таблиц.

То, что вы можете сделать в качестве обходного пути, на самом деле - это просто зарегистрировать собственный пользовательский диалект, как вы предлагали выше, с помощью JdbcDialects.registerDialect() до тех пор, пока упомянутый запрос на выборку не будет принят.

Обратите внимание, что DSX (т.е. datascience.ibm.com) не устранил эту проблему из коробки. Поэтому развертывание пользовательского диалекта больше не требуется при использовании ноутбуков в DSX с dashDB.

Другие вопросы по тегам