Spark SQL使用Presto JDBC报无法识别连接属性'url'如何解决
问题根因
Spark 3.1.1版本的JDBC数据源实现逻辑中,会将所有通过option传入的参数都作为连接属性透传给底层JDBC驱动,而Presto JDBC驱动会严格校验所有传入的连接属性,遇到无法识别的url属性就会直接抛出异常,这就是报错的直接原因。
可行的Workaround方案
下面三个方案都可以解决这个问题,你可以根据自己的场景选择:
方案1:使用JDBC重载方法传入URL(最简单,无需额外开发)
调用Spark JDBC的重载方法,将URL作为单独参数传入,不要放在option/Properties中,Spark就不会把URL作为连接属性透传给Presto驱动,有两种写法可选:
写法1:用query参数指定查询
import java.util.Properties val jdbcUrl = "jdbc:presto://localhost:8889/mycatalog" val connectionProps = new Properties() connectionProps.setProperty("driver", "com.facebook.presto.jdbc.PrestoDriver") connectionProps.setProperty("query", "select * from mydb.mytable limit 1") connectionProps.setProperty("user", "myuserid") // 第二个参数为占位符,不会实际生效 val df = spark.read.jdbc(jdbcUrl, "dummy", connectionProps)
写法2:用子查询作为表名参数
import java.util.Properties val jdbcUrl = "jdbc:presto://localhost:8889/mycatalog" val connectionProps = new Properties() connectionProps.setProperty("driver", "com.facebook.presto.jdbc.PrestoDriver") connectionProps.setProperty("user", "myuserid") // 将查询语句包装为子查询传入 val df = spark.read.jdbc(jdbcUrl, "(select * from mydb.mytable limit 1) as t", connectionProps)
方案2:自定义包装Presto驱动(适配原有链式写法)
如果不想修改现有链式调用的代码风格,可以自己写一个简单的Presto驱动包装类,过滤掉url属性后再调用原生Presto驱动:
package com.example import java.sql.{Connection, Properties} import com.facebook.presto.jdbc.PrestoDriver class WrappedPrestoDriver extends PrestoDriver { override def connect(url: String, info: Properties): Connection = { // 过滤掉Spark透传的url属性 info.remove("url") super.connect(url, info) } }
使用时只需要把原来的driver参数换成你自己的包装类即可:
val df = spark.read .format("jdbc") .option("driver", "com.example.WrappedPrestoDriver") .option("url", "jdbc:presto://localhost:8889/mycatalog") .option("query", "select * from mydb.mytable limit 1") .option("user", "myuserid") .load()
方案3:升级Spark版本(一劳永逸)
Spark从3.3.0版本开始修复了这个问题,内置的JDBC参数(url、dbtable、query等)不会再作为连接属性透传给驱动,升级到Spark 3.3.0及以上版本后,你最开始写的代码可以直接正常运行,无需任何修改。
内容的提问来源于stack exchange,提问作者Raj
相关产品推荐
相关产品推荐

