簡體   English   中英

SQLException上的sqlContext HiveDriver錯誤:不支持方法

[英]sqlContext HiveDriver error on SQLException: Method not supported

我一直在嘗試使用sqlContext.read.format("jdbc").options(driver="org.apache.hive.jdbc.HiveDriver")將Hive表放入Spark而沒有任何成功。 我做過研究並閱讀如下:

如何從spark連接到遠程配置單元服務器

Spark 1.5.1無法使用hive jdbc 1.2.0

http://belablotski.blogspot.in/2016/01/access-hive-tables-from-spark-using.html

我使用了最新的Hortonworks Sandbox 2.6並向社區詢問了同樣的問題:

https://community.hortonworks.com/questions/156828/pyspark-jdbc-py4jjavaerror-calling-o95load-javasql.html?childToView=156936#answer-156936

通過pyspark我想做的事情非常簡單:

df = sqlContext.read.format("jdbc").options(driver="org.apache.hive.jdbc.HiveDriver", url="jdbc:hive2://localhost:10016/default", dbtable="sample_07",user="maria_dev", password="maria_dev").load()

這給了我這個錯誤:

17/12/30 19:55:14 INFO HiveConnection: Will try to open client transport with JDBC Uri: jdbc:hive2://localhost:10016/default
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/hdp/current/spark-client/python/pyspark/sql/readwriter.py", line 139, in load
    return self._df(self._jreader.load())
  File "/usr/hdp/current/spark-client/python/lib/py4j-0.9-src.zip/py4j/java_gateway.py", line 813, in __call__
  File "/usr/hdp/current/spark-client/python/pyspark/sql/utils.py", line 45, in deco
    return f(*a, **kw)
  File "/usr/hdp/current/spark-client/python/lib/py4j-0.9-src.zip/py4j/protocol.py", line 308, in get_return_value
py4j.protocol.Py4JJavaError: An error occurred while calling o119.load.
: java.sql.SQLException: Method not supported
at org.apache.hive.jdbc.HiveResultSetMetaData.isSigned(HiveResultSetMetaData.java:143)
at org.apache.spark.sql.execution.datasources.jdbc.JDBCRDD$.resolveTable(JDBCRDD.scala:136)
at org.apache.spark.sql.execution.datasources.jdbc.JDBCRelation.<init>(JDBCRelation.scala:91)
at org.apache.spark.sql.execution.datasources.jdbc.DefaultSource.createRelation(DefaultSource.scala:57)
at org.apache.spark.sql.execution.datasources.ResolvedDataSource$.apply(ResolvedDataSource.scala:158)
at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:119)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:231)
at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:381)
at py4j.Gateway.invoke(Gateway.java:259)
at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:133)
at py4j.commands.CallCommand.execute(CallCommand.java:79)
at py4j.GatewayConnection.run(GatewayConnection.java:209)
at java.lang.Thread.run(Thread.java:748)

使用直線,它工作正常

beeline> !connect jdbc:hive2://localhost:10016/default maria_dev maria_dev
Connecting to jdbc:hive2://localhost:10016/default
Connected to: Spark SQL (version 2.1.1.2.6.1.0-129)
Driver: Hive JDBC (version 1.2.1000.2.6.1.0-129)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://localhost:10016/default> select * from sample_07 limit 2;
+----------+-------------------------+------------+---------+--+
|   code   |       description       | total_emp  | salary  |
+----------+-------------------------+------------+---------+--+
| 00-0000  | All Occupations         | 134354250  | 40690   |
| 11-0000  | Management occupations  | 6003930    | 96150   |
+----------+-------------------------+------------+---------+--+

我也可以這樣做:

spark = SparkSession.Builder().appName("testapp").enableHiveSupport().‌​getOrCreate()
spark.sql("select * from default.sample_07").collect()

但是這會直接讀入Hive元數據。 我想將JDBC用於Spark Thrift Server以實現細粒度的安全性。

我可以像這樣做PostgreSQL:

sqlContext.read.format("jdbc").options(driver="org.postgresql.Driver")

我還可以使用Scala java.sql.{DriverManager, Connection, Statement, ResultSet}來創建JDBC Connection作為客戶端來獲取Spark。 但這基本上將所有數據放入內存,然后手動重新創建Dataframe。

所以問題是:有沒有辦法用Hive表數據創建Spark數據幀而不將數據加載到像Scala這樣的JDBC客戶端中,而不是像上面的例子一樣使用SparkSession.Builder() 我的用例是我需要處理細粒度的安全性。

我不確定我是否正確理解你的問題,但是根據我的理解,你需要在數據框中獲得一個hive表,因為你不需要有JDBC連接,在你的示例鏈接中它們是嘗試連接到不同的數據庫(RDBMS),而不是Hive。

請參閱下面的方法,使用hive上下文,您可以將表格放入數據框中。

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.{DataFrame, SQLContext}

def main(args: Array[String]): Unit = {

val sparkConf = new SparkConf().setAppName("APPName")
    val sc = new SparkContext(sparkConf)
    val hiveContext = new org.apache.spark.sql.hive.HiveContext(sc)
    val sqlContext = new SQLContext(sc)

val hive_df = hiveContext.sql("select * from schema.table").first()

//other way
// val hive_df= hiveContext.table ("SchemaName.TableName")

//Below will print the first line
df.first()
//count on dataframe
df.count()

}

如果你真的想使用JDBC連接,我有以下用於Oracle數據庫的例子,這可能對你有所幫助。

val oracle_data = sqlContext.load("jdbc", Map("url" -> "jdbc:oracle:thin:username/password//hostname:2134/databaseName", "dbtable" -> "Your query tmp", "driver" -> "oracle.jdbc.driver.OracleDriver"));

其實我調查了這個。 Hotornworks和cloudera正在通過Thrift Server從Spark連接到hive的支持。

所以你正在做一些不可能的事情。

https://www.cloudera.com/documentation/spark2/latest/topics/spark2_known_issues.html#ki_thrift_server

鏈接說節儉是禁用的,但它是專門從火花蜂巢。 我可以從除了hive之外的spark連接到所有類型的數據庫。

因此,您必須處理不同類型的授權。

由於火花對象直接連接到蜂巢,他們正在移除節儉支撐。

從您之前的問題,它能夠讀取數據,但讀取錯誤的數據。 Spark 2.2 Thrift服務器在查詢Hive表時對數據幀NumberFormatException的錯誤

>>> df = sqlContext.read.format("jdbc").options(driver="org.apache.hive.jdbc.HiveDriver", url="jdbc:hive2://localhost:10016/default", dbtable="test4",user="hive", password="hive").option("fetchsize", "10").load()
>>> df.select("*").show()
+---+----+
| id|desc|
+---+----+
| id|desc|
| id|desc|
+---+----+

這里的問題在於蜂巢

默認方言中引用標識符的默認方式是使用雙引號。 像SELECT“dw_date”FROM table ...這樣的SQL查詢將由Hive解析以選擇字符串文字,而不是名為“dw_date”的列。 通過用反引號替換引號,問題似乎已得到解決。 但是,在我的測試中,來自Hive的列名稱都以表名為table.dw_date為前綴。 但是你不能像table.dw_date一樣直接包裹它的反引號。 或者,我們需要單獨包裝每個部分

import org.apache.spark.sql.jdbc.JdbcDialect
    private case object HiveDialect extends JdbcDialect {
      override def canHandle(url : String): Boolean = url.startsWith("jdbc:hive2")
      override def quoteIdentifier(colName: String): String = {
        colName.split(‘.’).map(part => s”`$part`”).mkString(“.”)
      }
    }

請按照下面的帖子來實施解決方案。

https://medium.com/@viirya/custom-jdbc-dialect-for-hive-5dbb694cc2bd

https://medium.com/@huaxing/customize-spark-jdbc-data-source-to-work-with-your-dedicated-database-dialect-beec6519af27

注冊方言

JdbcDialects.registerDialect(HiveDialect)

然后hive jdbc工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM