我正在尝试使用Spark的JDBC访问存储在远程集群上的表(ORC格式):
val jdbcDF = spark.read
.format("jdbc")
.option("url", url)
.option("dbtable", "metrics")
.option("user", user)
.option("password", password)
.load()
然而,无论我做什么,我都会收到这个错误:
引起:java.sql.SQLException:无法将第2列转换为long: java.lang.NumberFormatException:对于输入字符串:" metrics.t" at org.apache.hive.jdbc.HiveBaseResultSet.getLong(HiveBaseResultSet.java:372)at at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils $$ anonfun $ $组织阿帕奇$火花$ SQL $执行$ $的数据源JDBC $ JdbcUtils $$ makeGetter $ 8.apply(JdbcUtils.scala:365) 在 org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils $$ anonfun $ $组织阿帕奇$火花$ SQL $执行$ $的数据源JDBC $ JdbcUtils $$ makeGetter $ 8.apply(JdbcUtils.scala:364) 在 org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils $$匿名$ 1.getNext(JdbcUtils.scala:286) 在 org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils $$匿名$ 1.getNext(JdbcUtils.scala:268) 在org.apache.spark.util.NextIterator.hasNext(NextIterator.scala:73) 在 org.apache.spark.util.CompletionIterator.hasNext(CompletionIterator.scala:32) 在 org.apache.spark.sql.catalyst.expressions.GeneratedClass $ GeneratedIterator.processNext(未知 来源)at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43) 在 org.apache.spark.sql.execution.WholeStageCodegenExec $$ anonfun $ 8 $$不久$ 1.hasNext(WholeStageCodegenExec.scala:377) 在 org.apache.spark.sql.execution.SparkPlan $$ anonfun $ 2.适用(SparkPlan.scala:231) 在 org.apache.spark.sql.execution.SparkPlan $$ anonfun $ 2.适用(SparkPlan.scala:225) 在 org.apache.spark.rdd.RDD $$ anonfun $ mapPartitionsInternal $ 1 $$ anonfun $ $申请25.apply(RDD.scala:826) 在 org.apache.spark.rdd.RDD $$ anonfun $ mapPartitionsInternal $ 1 $$ anonfun $ $申请25.apply(RDD.scala:826) 在 org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38) 在org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:323) 在org.apache.spark.rdd.RDD.iterator(RDD.scala:287)at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)at at org.apache.spark.scheduler.Task.run(Task.scala:99)at org.apache.spark.executor.Executor $ TaskRunner.run(Executor.scala:282) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 在 java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:617) 在java.lang.Thread.run(Thread.java:745) 引起: java.lang.NumberFormatException:对于输入字符串:" metrics.t" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) 在java.lang.Long.parseLong(Long.java:589)at java.lang.Long.parseLong(Long.java:631)at org.apache.hive.jdbc.HiveBaseResultSet.getLong(HiveBaseResultSet.java:368) ......还有22个
输入字符串" metrics.t"对应于第二列的表名和名称," t",其中包含时间戳。
如何跳过带有JDBC格式的标题?
CSV选项("标题",true)对我的情况无效。
PS:Spark版本2.1.0
答案 0 :(得分:1)
代码不会抛出以下实现的任何异常:
val jdbcUrl = s"jdbc:hive2://$jdbcHostname:$jdbcPort/$jdbcDatabase"
val connectionProperties = new java.util.Properties()
connectionProperties.setProperty("user", jdbcUsername)
connectionProperties.setProperty("password", jdbcPassword)
val jdbcDF = spark.read.jdbc(jdbcUrl, "metrics", Array(), connectionProperties)
奇怪的是,如果我删除空谓词Array()
,则会再次返回异常。
答案 1 :(得分:1)
我在初始化SparkSession时启用了Hive支持,对我有用:
def Regional_category(self, response):
names = {'name1':'Regional_subcategories',
'name2':'Related_Categories',
'name3':'Site title',
'name4':'Site Description',
}
finder = {'finder1': '.browse-node::text',
'finder2': '.one-browse-node::text',
'finder3': '.site-title::text',
'finder4': '.site-descr::text',
}
yield from self.find_items(response, names, finder)
答案 2 :(得分:0)
因为Spark JdbcDialect使用双引号作为quoteIdentifier,它不提供HiveDialect(不像MySQL)。
因此,Spark会通过JDBC将此类SQL发送到Hive:select "some_column_name" from table
,而"some_column_name"
结果是字符串标量而不是列名。
val jdbcDF = spark.read.jdbc(jdbcUrl, "metrics", Array(), connectionProperties)
,您告诉Spark生成没有任何分区的JDBC DataFrame。因此没有实际的数据获取SQL被发送到Hive,而Spark只给你一个空的DataFrame。
唯一正确的方法是实施相应的方言: How to specify sql dialect when creating spark dataframe from JDBC?