Bigquery - Spark的Simba JDBC错误

时间:2017-10-30 16:49:12

标签: scala apache-spark jdbc google-bigquery

我正在尝试使用Simba JDBC Driver(bigquery jdbc 4.2)从apache spark 2.2.0查询bigquery

这是我的代码:

import spark.implicits._
import org.apache.spark.sql.SQLContext
val sqlcontext = new org.apache.spark.sql.SQLContext(sc)
val pushdown_query = "(select * from mydb.mytable) AS T"
val dataframe_bq = sqlcontext.read.format("jdbc").option("url","jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;ProjectId=xxxx;OAuthType=0;OAuthServiceAcctEmail==xxxxxxx@xxxxxx.iam.gserviceaccount.com;OAuthPvtKeyPath=/path/file.json;").option("driver", "com.simba.googlebigquery.jdbc42.Driver").option("dbtable", pushdown_query).load()
dataframe_bq.show()

这是错误:

org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 3.0 failed 1 times, most recent failure: Lost task 0.0 in stage 3.0 (TID 3, localhost, executor driver): java.sql.SQLDataException: 

[Simba][JDBC](10140) Error converting value to Timestamp.

任何数据类型都可能发生转换错误,例如:

[Simba][JDBC](10140) Error converting value to Long.

Spark 2.x让每个columnName都被双引号!

所以例如SELECT UserID,UserName FROM USERS

将被操纵为SELECT“UserID”,“UserName”FROM USERS

数据框看起来像这样:

+------+--------+ 
|UserID|UserName| 
+------+--------+ 
|UserID|UserName| 
|UserID|UserName| 
|UserID|UserName| 
+------+--------+ 

建议的解决方案是编写自定义spark JDBC方言,但我还不能让它正常运行。

如果您能告诉我如何解决此问题,我感谢您。 提前谢谢。

4 个答案:

答案 0 :(得分:1)

问题是,一种预先注册的jdbc方言在字段名周围添加了额外的引号。

所以查询-select column1,column2 from table变成了select "column1","column2" from table

要解决spark中的问题,请在创建spark上下文之后和创建数据框之前添加以下代码。 [此解决方案专用于SIMBA驱动程序]

JdbcDialects.registerDialect(new JdbcDialect() {

override def canHandle(url: String): Boolean = url.toLowerCase.startsWith("jdbc:bigquery:")

override

def quoteIdentifier(column: String): String =  column

})

答案 1 :(得分:0)

面对同样的问题。

如果需要使用Spark JDBC,除了使用/实现自定义JDBC方言外,没有其他选择。您可以看一下https://github.com/trK54Ylmz/spark-bigquery,它做了些微的改动对我有用。

如果不需要JDBC,您还可以尝试以下可用的连接器之一:Spotify(目前处于维护模式),Dataproc的Google本机connector(不幸的是非常有限)或{ {3}}第三方版本,看起来很有希望。

答案 2 :(得分:0)

要解决此问题,我必须编辑Apache Spark 2.1版源代码,并使用以下过程重新编译它以处理此问题:

1)先决条件

 Maven 3.3.9 or newer and Java 8+ 

2)下载spark源代码,在我的情况下是2.1版

3)更新源代码,以防止Spark在列名中添加双引号!,搜索下面的代码并相应地替换它。

源代码引用文件https://github.com/apache/spark/blob/branch-2.1/sql/core/src/main/scala/org/apache/spark/sql/jdbc/JdbcDialects.scala#L90

编辑此功能:

def quoteIdentifier(colName: String): String = {
    s""""$colName""""
}

并使它像这样:


def quoteIdentifier(colName: String): String = {
    return colName
}

4)用Maven构建它

  Install maven 3.3.9 or above and java 8 and then build it:
    ./dev/make-distribution.sh --name custom-spark --pip --r --tgz -Psparkr -Phadoop-2.7 -Phive -Phive-thriftserver -Pmesos -Pyarn

希望对您有帮助。

答案 3 :(得分:0)

当我将Simba jdbc驱动程序用于Spark时,选项 UseNativeQuery = 0 解决了以下问题:

[Simba][JDBC](10140) Error converting value to Timestamp

所以希望我不必开发任何特定的方言。