天天看點

spark連接配接hive(spark-shell和eclipse兩種方式)

版權聲明:本文由董可倫首發于https://dongkelun.com,非商業轉載請注明作者及原創出處。商業轉載請聯系作者本人。 https://blog.csdn.net/dkl12/article/details/80248716

我的原創位址:

http://dongkelun.com/2018/03/25/sparkHive/

1、在伺服器(虛拟機)spark-shell連接配接hive

1.1 将hive-site.xml拷貝到spark/conf裡

cp /opt/apache-hive-2.3.2-bin/conf/hive-site.xml /opt/spark-2.2.1-bin-hadoop2.7/conf/
           

1.2 将mysql驅動拷貝到spark/jar裡

cp /opt/apache-hive-2.3.2-bin/bin/mysql-connector-java-5.1.46-bin.jar /opt/spark-2.2.1-bin-hadoop2.7/jars/
           

1.3 啟動spark-shell,輸入代碼測試

spark-shell
import org.apache.spark.sql.hive.HiveContext
val hiveContext = new HiveContext(sc)
hiveContext.sql("select * from test").show()
           

1.4 異常及解決

在執行hiveContext.sql(“select * from test”).show() 報了一個異常:

The root scratch dir: /tmp/hive on HDFS should be writable. Current permissions are: rwxr-xr-x;
           

解決辦法:

1.4.1 更改HDFS目錄/tmp/hive的權限:

hadoop fs -chmod 777 /tmp/hive
           

1.4.2 同時删HDFS與本地的目錄/tmp/hive:

hadoop fs -rm -r /tmp/hive 
rm -rf /tmp/hive
           

這次錯誤采用的是第二種解決辦法,有的情況下用第一種方法,比如一次在啟動hive時候報這種錯誤~。

錯誤截圖:

參考:

http://www.cnblogs.com/czm1032851561/p/5751722.html

2、win10+eclipse上連接配接hive

2.1 将hive-site.xml拷貝到項目中的resources檔案夾下

2.2 在sbt裡添加對應版本的mysql依賴

"mysql" % "mysql-connector-java" % "5.1.46"
           

2.3 代碼

2.3.1 舊版api(1.6以上)

package com.dkl.leanring.spark.sql

import org.apache.spark.SparkConf
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.hive.HiveContext
import org.apache.spark.SparkContext

/**
 * 舊版本spark-hive測試
 */
object OldSparkHiveDemo {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("OldSparkHiveDemo").setMaster("local")
    val sc = new SparkContext(conf)
    val sqlContext = new SQLContext(sc)
    import sqlContext.implicits._
    val hiveCtx = new HiveContext(sc)

    hiveCtx.sql("select * from test").show()
    val data = Array((3, "name3"), (4, "name4"), (5, "name5"))
    val df = sc.parallelize(data).toDF("id", "name")
    df.createOrReplaceTempView("user")
    hiveCtx.sql("insert into test select id,name from user")
    hiveCtx.sql("select * from test").show()
  }

}
           

(注:其中df.createOrReplaceTempView(“user”)改為df.registerTempTable(“user”),因為createOrReplaceTempView方法是2.0.0才有的,registerTempTable是舊版的方法,1.6.0就有了,嫌麻煩就不改代碼重新貼圖了)

2.3.2 新版api

package com.dkl.leanring.spark.sql

import org.apache.spark.sql.SparkSession

/**
 * 新版本spark-hive測試
 */
object NewSparkHiveDemo {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession
      .builder()
      .appName("Spark Hive Example")
      .master("local")
      .config("spark.sql.warehouse.dir", "/user/hive/warehouse/")
      .enableHiveSupport()
      .getOrCreate()

    import spark.implicits._
    import spark.sql
    sql("CREATE TABLE IF NOT EXISTS src (key INT, value STRING)")
    val data = Array((1, "val1"), (2, "val2"), (3, "val3"))
    var df = spark.createDataFrame(data).toDF("key", "value")
    df.createOrReplaceTempView("temp_src")
    sql("insert into src select key,value from temp_src")
    sql("SELECT * FROM src").show()
  }
}
           

2.4 異常及解決方法

在執行insert語句時會出現如下異常資訊:

org.apache.hadoop.security.AccessControlException: Permission denied: user=dongkelun, access=EXECUTE, inode="/user/hive/warehouse":root...
           

原因是:啟動 Spark 應用程式的win使用者對spark.sql.warehouse.dir沒有寫權限

hadoop fs -chmod 777 /user/hive/warehouse/
           

附異常資訊截圖:

3、更新:寫hive方法

直接用下面這句代碼即可将df裡的全部資料存到hive表裡

df.write.mode(SaveMode.Append).saveAsTable(tableName)
           

4、更新(2018.11.29)

4.1 關于hive-site.xml

上面講的hive-site.xml為我在部落格

centos7 hive 單機模式安裝配置

配置的。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
 <property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://192.168.44.128:3306/hive_metadata?&amp;createDatabaseIfNotExist=true&amp;characterEncoding=UTF-8&amp;useSSL=false</value>
 </property>
<property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>root</value>
</property>
<property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>Root-123456</value>
</property>
<property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.jdbc.Driver</value>
</property>
<property>
    <name>datanucleus.schema.autoCreateAll</name>
    <value>true</value> </property>
<property>
    <name>hive.metastore.schema.verification</name>
    <value>false</value>
 </property>
</configuration>
           

後來在工作中發現可以不用将整個hive-site.xml全部拷過來,用一個metastore就可以搞定~

用下面的指令啟動metastore

nohup hive --service metastore &
           

在nohup.out檔案裡看一下啟動日志,如果啟動成功的話,就可以将hive-site.xml改為

<configuration>
	<property>
		<name>hive.metastore.uris</name>
      	<value>thrift://192.168.44.128:9083</value>
	</property>
 </configuration>
           

這樣就可以用上面講的代碼連接配接Hive了,一般我都是用這種方式連接配接Hive,至于優缺點我沒有深入研究,表面上看起來有兩點

  • 配置比較簡單
  • 不用暴漏中繼資料庫mysql的使用者名、密碼等。
如何關閉metastore(Linux基礎)
-bash-4.2# ps aux | grep metastore
root       8814  2.6  6.2 2280480 240040 pts/0  Sl   03:10   0:18 /opt/jdk1.8.0_45/bin/java -Xmx256m -Djava.net.preferIPv4Stack=true -Dhadoop.log.dir=/opt/hadoop-2.7.5/logs -Dhadoop.log.file=hadoop.log -Dhadoop.home.dir=/opt/hadoop-2.7.5 -Dhadoop.id.str=root -Dhadoop.root.logger=INFO,console -Djava.library.path=/opt/hadoop-2.7.5/lib/native -Dhadoop.policy.file=hadoop-policy.xml -Djava.net.preferIPv4Stack=true -Xmx512m -Dhadoop.security.logger=INFO,NullAppender org.apache.hadoop.util.RunJar /opt/apache-hive-2.3.2-bin/lib/hive-metastor-2.3.2.jar org.apache.hadoop.hive.metastore.HiveMetaStore
root       9073  0.0  0.0 114724   984 pts/0    S+   03:22   0:00 grep --color=auto metastore
-bash-4.2# kill 8814

           

4.2 另一個讀取hive表的簡單方法

用下面這行代碼就可以讀取整個Hive表了

spark.table("test")
           

4.3 關于上面的代碼

下面這個配置可以去掉

.config("spark.sql.warehouse.dir", "/user/hive/warehouse/")