web-dev-qa-db-ja.com

SQLExceptionでのsqlContextHiveDriverエラー:メソッドはサポートされていません

私はsqlContext.read.format("jdbc").options(driver="org.Apache.Hive.jdbc.HiveDriver")を使用してHiveテーブルをSparkに入れることに成功しませんでした。調査を行い、以下を読みました。

sparkからリモートHiveサーバーに接続する方法

Spark1.5.1がHivejdbc 1.2.0で機能しない

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

私は最新のHortonworksSandbox 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を使用すると、正常に機能します

_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}_を使用して、Sparkにアクセスするためのクライアント側としてJDBC接続を作成することもできます。ただし、基本的にすべてのデータをメモリに入れてから、手動でデータフレームを再作成します。

したがって、問題は次のとおりです。SparkのようにメモリにデータをロードせずにHiveテーブルデータを使用してScalaデータフレームを作成し、SparkSession.Builder()上記の例のように?私の使用例は、きめ細かいセキュリティを処理する必要があるということです。

21
HP.

私があなたの質問を正しく理解しているかどうかはわかりませんが、私が理解していることから、Hiveテーブルをデータフレームに入れる必要があります。JDBC接続を持っている必要はありません。 Hiveではなく別のデータベース(RDBMS)に接続しようとしています。

以下のアプローチを参照してください。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"));
3
roh

実はこれを調べました。 Hotornworksとclouderaは、Thriftサーバーを介してSparkからHiveに接続するためのサポートをかがめています。

だからあなたは不可能なことに取り組んでいます。

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

リンクは、倹約が無効になっていると言っていますが、それは特に火花からハイブに向けられています。 spark Hiveを除くすべてのタイプのデータベースに接続できます。

したがって、さまざまなスタイルの承認に取り組む必要があります。

sparkオブジェクトはHiveに直接接続しているため、節約サポートを削除しています。

前の質問から、データを読み取ることはできますが、間違ったデータを読み取ることができます。 HiveテーブルをクエリするときのデータフレームNumberFormatExceptionでのSpark 2.2 Thriftサーバーエラー

コード

>>> 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|
+---+----+

ここでの問題はHiveにあります

識別子を引用するデフォルトの方言のデフォルトの方法は、二重引用符を使用することです。 SELECT“ dw_date” FROM table…のようなSQLクエリは、“ dw_date”という名前の列ではなく、文字列リテラルを選択するためにHiveによって解析されます。引用符をバッククォートに置き換えることで、問題は解決したようです。ただし、私のテストでは、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)

その後、Hivejdbcが機能します。

0
Achyuth