1. 程式人生 > >大資料學習之路92-sparkSQL整合hive

大資料學習之路92-sparkSQL整合hive

我們知道sparkSQL跟hive是相容的,他支援hive的元資料庫,sql語法,多種型別的UDF,

而且還支援hive的序列化和反序列化方式,意思就是hive寫的自定義函式,spark拿過來就能用。

最重要的就是MetaStore元資料庫,以後一旦我們使用hive的MetaStore,那麼他以前建的表我們就可以使用了。

那麼我們寫的SQL就可以直接從hive的倉庫中查詢資料了。

所謂hive的倉庫其實就是一個元資料庫和hdfs

元資料庫中指定了有哪些表,表中有哪些欄位。每個欄位叫什麼名字,分別是什麼型別。還有這張表對應的存放在hdfs的哪個目錄下。以後我們執行sparksql的時候就可以根據元資料資訊到hdfs中找對應的資料了。

元資料庫中存放的是描述資訊,hdfs中存放的是真正需要計算的資訊。

接下來我們來整合hive,其實整合hive就是整合hive的元資料庫,hive的sql,UDF,還有序列化

假設我們以前用過hive或者沒用過hive,我們都可以將他整合進來。如果有的話就直接拿過來用,沒有的話就新建一個。

我們之前使用hive的時候,如果配置了mysql的元資料庫,一執行任務就會在mysql中建立。

所以當我們使用sparkSQL的時候,如果還沒有建立元資料庫,sparkSQL就會幫我們建立。

--------------------------------------------------------------------------------------------------------------------------------------

接下來我們就來整合hive,我們知道,玩hive的話,首先要啟動hdfs,所以我們需要先將需要的環境先啟動起來。

接下來的步驟:

1.安裝hive(可選),我們可以選擇安裝或者不安裝hive,這時候有人就會問了,不安裝hive怎麼將spark整合hive?

其實我們用hive只是用的hive的元資料庫,我們都不用他的jar包。如果這個元資料庫以前有,那更好,我們可以直接拿過來用。

如果hive沒有元資料庫怎麼辦?我們可以讓spark幫我們建立一個。

sparkSQL在第一次啟動的時候他會找元資料庫。會在我們指定的mysql的位置看看有沒有我們指定的相應的元資料庫。

有的話就用原來的,沒有的話就建立一個。

其實sparkSQL也會建立一個元資料庫。和hive建立的是一樣的。

2.在mysql中建立使用者並賦予許可權:
 

create user 'root'@'%' identified by '123456';

grant all privileges on hivedb.* to 'root'@'%';

flush privileges;

第二步完成之後,前期準備就已經準備好了。

3.將配置好的hive-site.xml放入$SPARK-HOME/conf目錄下

注意:整合hive他唯一需要的其實就是一個hive配置檔案。

那麼這個檔案我們放到什麼地方呢?是放到所有機器還是放到一臺機器?

以前我們用hiveshell其實他只要安裝一臺機器就可以了。他就是一個sql解析引擎,他是一個客戶端,他會把我們的sql解析成MapReduce。通過客戶端提交到叢集上。

sparkSQL也是一樣的,他只要安裝一臺就可以了。他可以將我們寫的sql轉換成RDD然後再把它提交到叢集。

那麼這個sparkSQL也相當於是一個客戶端。

4.將hadoop的core-site.xml和hdfs-site.xml都放入spark的conf目錄下

這個時候問題就來了,我們為什麼需要這兩個配置檔案?

因為以後我們執行hivesql的時候他需要將hiveSQL轉換成RDD在叢集當中執行。那麼以後他需要在hdfs當中讀取資料。

要讀取資料就需要知道namenode在哪裡。而namenode的一些資訊就放在core-site.xml當中

如果我們配置的是高可用叢集的話,那麼hdfs-site.xml當中也有namenode的資訊。

5.然後啟動hdfs,接下來啟動spark

6.執行spark-sql並指定mysql連線驅動位置

接下來我們想讓他幫我們建立一個元資料庫,我們第一次不啟動sparkshell,

我們啟動sparksql
 

bin/spark-sql \

--master spark://marshal:7077 \

--driver-class-path /root/mysql-connector-java-5.1.21-bin.jar

這裡的命令sparkSQL需要指定master的地址。

指定driver-class-path是因為sparkSQL需要連線元資料庫,這個時候就用到了mysql的連線驅動。

其實這裡我們這樣啟動,是會報錯的,因為它還要找hadoop的配置檔案。而我們把那些配置檔案放入conf目錄,它也是找不到的。這個時候我們就需要在etc/profile中配置一下HADOOP_CONF_DIR:

配置完這個之後啟動sparkSQL的時候就可以知道hdfs所有的配置檔案了。

然後我們將原來的元資料庫刪掉。

之後執行命令就可以看到資料庫中生成了hive的元資料庫,而且DBs表中DB_LOCATION_URI應該是hdfs的路徑而不是本地。

這個引數說明了hive的資料庫在hdfs中的位置

成功截圖:

接下來我們嘗試在sparkSQL中建立一張表

我們建立的表在資料庫中的TBL表中即可檢視:

所以我們發現,現在我們在sparkSQL中就可以寫hive的語句了。

於是我們嘗試使用load將資料寫入hdfs上再通過語句查詢出來,首先我們來造一下資料:

然後載入資料到hdfs:

然後我們在hdfs中檢視一下:

接下來我們查詢一下:

這個時候有人就會產生疑問,我們現在使用的這些語句和Hive一模一樣啊

包括我們剛才建立hive的表,load資料的語法和hive一模一樣啊。

那麼我們使用sparksql和hive有什麼區別呢?

其實是執行引擎換了,原來我們的執行引擎是用mapreduce執行的。而現在使用的是spark,底層是RDD。

執行結果如下:

接著我們可以寫程式去訪問,在寫程式之前,我們需要將配置檔案放入resources目錄:

程式碼如下:

package com.test.SparkSQL

import org.apache.spark.sql.SparkSession

object SparkSQLHive {
  def main(args: Array[String]): Unit = {
    val spark: SparkSession = SparkSession.builder()
      .appName("SparkSQLHive")
      .master("local[*]")
      .enableHiveSupport()
      .getOrCreate()
    spark.sql("select * from t_user").show()
  }
}

執行結果如下:

sparksql還可以整合hive的自定義函式:

我們先來寫一個自定義函式:

然後造資料,並載入到hive表中

首先建立表:

然後造資料:

接著載入資料:

然後在程式碼中使用自定義函式:

程式碼如下:

package com.test.SparkSQL

import org.apache.spark.sql.SparkSession

object SparkSQLHive {
  def main(args: Array[String]): Unit = {
    val spark: SparkSession = SparkSession.builder()
      .appName("SparkSQLHive")
      .master("local[*]")
      .enableHiveSupport()
      .getOrCreate()
   // spark.sql("select * from t_user").show()
    spark.sql("create temporary function ip2Long as 'com.xiaoniu.udf.IpToLong'")
    spark.sql("select id,ip,ip2Long(ip) from access_log").show()
  }

}

執行結果如下: