2016-11-23 4 views
3

Я работаю, чтобы подключить мое искровое приложение к DashDB. В настоящее время я могу загрузить свои данные просто отлично.Spark JDBC to DashDB (DB2) с ошибками CLOB

Однако я не могу сохранить 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, я получаю ошибку:

DB2 SQL Error: 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) 

Я посмотрел на DB2Dialect и JDBC видим, что код 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 
    } 
} 

ответ

1

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

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

На данный момент вы можете использовать собственный диалект, как вы предлагаете выше, с JdbcDialects.registerDialect(), пока не будет принят упомянутый запрос на растяжение.

+0

У меня такая же проблема, но я использую PySpark. Как я могу это исправить? –

+0

Вы можете применить это исправление также в ноутбуках PySpark, используя функцию Scala bridge от Pixidust. Я написал статью в блоге о всей проблеме и решении со ссылками на примеры ноутбуков здесь: http://datascience.ibm.com/blog/working-with-dashdb-in-data-science-experience/ –

+0

Я видел это в статье, я на самом деле использую IBM-источник-источник, а не ноутбуки/DSX. Вы говорите, что мне нужно исправить мой сценарий локально, а затем отправить его в Spark Cluster? Будет ли в Spark Cluster установлены все эти зависимости, поскольку это управляемая служба? –

1

Хорошо работает, добавляя индивидуальный диалект.

JdbcDialects.registerDialect(new DB2CustomDialect()) 
0

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

Смежные вопросы