spark on hive原理與環境搭建 spark研習第三季
SparkSQL前身是Shark,Shark強烈依賴於Hive。Spark原來沒有做SQL多維度資料查詢工具,後來開發了Shark,Shark依賴於Hive的解釋引擎,部分在Spark中執行,還有一部分在Hadoop中執行。所以講SparkSQL必須講Hive。
一、spark on hive原理與搭建
1. hive的本質
1)Hive是分散式資料倉庫,同時又是查詢引擎,所以SparkSQL取代的只是Hives的查詢引擎,在企業實際生產環境下,Hive+SparkSQL是目前最為經典的資料分析組合。
2)Hive本身就是一個簡單單機版本的軟體,主要負責:
A) 把HQL翻譯成Mapper(s)-Reducer-Mapper(s)的程式碼,並且可能產生很多MapReduce的JOB。 B)把生成的MapReduce程式碼及相關資源打包成jar併發布到Hadoop叢集中執行(這一切都是自動的)
3)Hive本身的架構如下所示:
hive架構
可以通過CLI(命令終端)、JDBC/ODBC、Web GUI訪問Hive。
JavaEE或.net程式可以通過Hive處理,再把處理的結果展示給使用者。
也可以直接通過Web頁面操作Hive。
※ Hive本身只是一個單機版本的的軟體,怎麼訪問HDFS的呢?
=> 在Hive用Table的方式插入資料、檢索資料等,這就需要知道資料放在HDFS的什麼地方以及什麼地方屬於什麼資料,Metastore就是儲存這些元資料資訊的。Hive通過訪問元資料資訊再去訪問HDFS上的資料。
可以看出HDFS不是一個真實的檔案系統,是虛擬的,是邏輯上的,HDFS只是一套軟體而已,它是管理不同機器上的資料的,所以需要NameNode去管理元資料。DataNode去管理資料。
Hive通過Metastore和NameNode打交道。
2. Hive安裝和配置實戰
Spark1.6.1中SparkSQL可以指定具體的Hive的版本。
1) 從apache官網下載hive-1.2.1,並解壓到/home/richard目錄。
http://mirrors.cnnic.cn/apache/hive/hive-1.2.1/
2) 配置.bashrc,追加以下內容,或者/etc/profile:
export HIVE_HOME=/home/richard/hive-1.2.1
export HIVE_CONF_DIR=/$HIVE_HOME/conf
export PATH=$PATH:$HIVE_HOME/bin
3)進入/home/richard/hive-1.2.1/conf目錄,生成hive-env.sh:
cp hive-default.xml.template hive-site.xml
配置:
export HADOOP_HOME=/opt/hadoop-2.6.0
export HIVE_HOME=/opt/hive-1.2.1/
export HIVE_CONF_DIR=/opt/hive-1.2.1/conf
Hive預設情況下放元資料的資料庫是Derby,遺憾的是Derby是單使用者,所以在生產環境下一般會採用支援多使用者的資料庫來進行MetaStore,且進行Master-Slaves主從讀寫分離和備份(一般Master節點負責寫資料,Slaves節點負責讀資料)。最常用的是MySQL。
cp hive-env.sh.template hive-env.sh
再生成hive-site.xml,並配置如下:
<configuration>
<!-- WARNING!!! This file is auto generated for documentation purposes ONLY! -->
<!-- WARNING!!! Any changes you make to this file will be ignored by Hive. -->
<!-- WARNING!!! You must make your changes in hive-site.xml instead. -->
<!-- Hive Execution Parameters -->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://master:3306/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>778899..</value>
<description>password to use against metastore database</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>
</configuration>
Hive中的DataBase和表其實就是HDFS上的目錄和簡單的文字檔案。簡單的文字檔案中有幾列資料,每列資料的型別無法直接從文字檔案中得知。但當資料放入Hive中,Hive就把元資料放入Mysql中了,這樣就可以基於資料的表進行查詢了。
hive開啟錯誤參考:
主要是按照《DT-大資料 hive1.2.1用mysql作為元資料庫搭建》文件
另外還需要下載驅動包(mysql-connector-java-5.1.35.tar.gz)將.jar檔案放到這個目錄下:
cd /usr/local/hive/apache-hive-1.2.1/lib/
啟動hive報錯
Logging initialized using configuration in jar:file:/opt/hive-1.2.1/lib/hive-common-1.2.1.jar!/hive-log4j.properties
Exceptionin thread "main" java.lang.RuntimeException: java.lang.RuntimeException:Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient
Causedby: java.lang.RuntimeException:Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient
Causedby: java.lang.reflect.InvocationTargetException
Causedby: javax.jdo.JDOFatalDataStoreException:Unable to open a test connection to the given database. JDBC url = jdbc:mysql://master:3306/hive?createDatabaseIfNotExist=true, username = hive. Terminating connection pool (set lazyInit to true if you expect to start your database after
...
[email protected]:/opt# netstat -tnlp | grep 3306
tcp 00127.0.0.1:33060.0.0.0:* LISTEN 5090/mysqld
//mysql的監聽IP應該是0.0.0.0
//在vi /etc/mysql/my.cnf 中修改
killall mysqld 後守護程序還會啟動mysql,等於重啟
另外報錯:
SLF4J:See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J:Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
[ERROR]Terminal initialization failed; falling back to unsupported
原因是hadoop目錄下存在老版本jline:
/hadoop-2.5.2/share/hadoop/yarn/lib:
-rw-r--r-- 1 root root 87325 Mar 10 18:10 jline-0.9.94.jar
解決方法是:
將hive下的新版本jline的JAR包拷貝到hadoop下:
cp /hive/apache-hive-1.1.0-bin/lib/jline-2.12.jar ./
5) Hive的表有兩種基本型別:一種是內部表(這種表資料屬於Hive本身,即如果原來的資料在HDFS的其他地方,此時資料會通過HDFS移動到Hive所在目錄,如果刪除Hive中的該表的話資料和元資料均會被刪除),一種是外部表(這種表資料不屬於Hive資料倉庫,元資料中會表達具體資料在哪裡,使用時和內部表的使用一樣,只是如果通過Hive去刪除的話,刪除的只是元資料,並沒有刪除資料本身)
6)Hive擴充套件(Hive的資料儲存-轉載)
Hive是基於Hadoop分散式檔案系統的,它的資料儲存在Hadoop分散式檔案系統中。Hive本身是沒有專門的資料儲存格式,也沒有為資料建立索引,只需要在建立表的時候告訴Hive資料中的列分隔符和行分隔符,Hive就可以解析資料。所以往Hive表裡面匯入資料只是簡單的將資料移動到表所在的目錄中(如果資料是在HDFS上;但如果資料是在本地檔案系統中,那麼是將資料複製到表所在的目錄中)。
Hive中主要包含以下幾種資料模型:Table(表),External Table(外部表),Partition(分割槽),Bucket(桶)(本部落格會專門寫幾篇博文來介紹分割槽和桶)。
1、表:Hive中的表和關係型資料庫中的表在概念上很類似,每個表在HDFS中都有相應的目錄用來儲存表的資料,這個目錄可以通過${HIVE_HOME}/conf/hive-site.xml配置檔案中的 hive.metastore.warehouse.dir屬性來配置,這個屬性預設的值是/user/hive/warehouse(這個目錄在 HDFS上),我們可以根據實際的情況來修改這個配置。如果我有一個表wyp,那麼在HDFS中會建立/user/hive/warehouse/wyp 目錄(這裡假定hive.metastore.warehouse.dir配置為/user/hive/warehouse);wyp表所有的資料都存放在這個目錄中。這個例外是外部表。
2、外部表:外部表指向已經在HDFS中存在的資料,可以建立Partition。它和內部表在元資料的組織上是相同的,而實際資料的儲存則有較大的差異。內部表的建立過程和資料載入過程這兩個過程可以分別獨立完成,也可以在同一個語句中完成,在載入資料的過程中,實際資料會被移動到資料倉庫目錄中;之後對資料對訪問將會直接在資料倉庫目錄中完成。刪除表時,表中的資料和元資料將會被同時刪除。而外部表只有一個過程,載入資料和建立表同時完成(CREATE EXTERNAL TABLE ……LOCATION),實際資料是儲存在LOCATION後面指定的 HDFS 路徑中,並不會移動到資料倉庫目錄中。當刪除一個External Table時,僅刪除該連結。
3、分割槽:在Hive中,表的每一個分割槽對應表下的相應目錄,所有分割槽的資料都是儲存在對應的目錄中。比如wyp 表有dt和city兩個分割槽,則對應dt=20131218,city=BJ對應表的目錄為/user/hive/warehouse /dt=20131218/city=BJ,所有屬於這個分割槽的資料都存放在這個目錄中。
4、桶:對指定的列計算其hash,根據hash值切分資料,目的是為了並行,每一個桶對應一個檔案(注意和分割槽的區別)。比如將wyp表id列分散至16個桶中,首先對id列的值計算hash,對應hash值為0和16的資料儲存的HDFS目錄為:/user /hive/warehouse/wyp/part-00000;而hash值為2的資料儲存的HDFS 目錄為:/user/hive/warehouse/wyp/part-00002。如果想應用很多的Map任務這樣是不錯的選擇。
Hive資料抽象結構圖
3. 使用Hive分析搜尋資料
啟動HDFS/Yarn。注意如果要使用Hive進行查詢就需要啟動Yarn。
啟動Hive。
通過show databases;可以檢視資料庫。預設database只有default。
選取搜狗實驗的三個資料來源:http://download.labs.sogou.com/dl/q.html
hadoop dfs -mkdir /library/sogou
hadoop dfs -put ./SogouQ1.txt /library/sogou
hadoop dfs -put ./SogouQ2.txt /library/sogou
hadoop dfs -put ./SogouQ3.txt /library/sogou
create table SogouQ3(ID STRING, WEBSESSION STRING, WORD STRING, S_SEQ INT, C_SEQ INT, WEBSITE STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n';//建表
LOAD DATA INPATH '/library/sogou/SogouQ3.txt' OVERWRITE INTO TABLE SogouQ3;//載入資料
查詢搜尋排名第一,點選排名為第一的結果:
select count(*) from sogouq1 where S_SEQ=1 and C_SEQ=1;
搜尋日誌中,關注排名前五的內容,並且給出分別為多少次:
select WORD, count(WORD) as COUNTWord from SogouQ1 group by WORD order by COUNTWord desc limit 5
查詢例子mysql
mysql -u root -p
creeate database hive;
use hive;
create table person(name String,age int);
insert into person values(‘richard’,’34’);
select*from person;即可查詢。
到此不需要啟動spark,只需要啟動HDFS。
4. Spark SQL on Hive配置及實戰
1)spark on hive 配置
- 切換到spar的conf目錄下使用vi hive-site.xml建立hive-site.xml.並填寫如下內容
<configuration>
<property>
<name>hive.metastore.uris</name>
<value>thrift://master:9083</value>
<description>thrift URI for the remote metastore.Used by metastore client to connect to remote metastore. </description>
</property>
</configuration>
因為用sparksql操作hive實際上是把hive 當做資料倉庫。資料倉庫肯定有元資料和資料本身。要訪問真正的資料就要訪問他的元資料。所以只需要配置hive.metastore.uris即可。(不需在每臺機器上配置)
2)啟動叢集
- 啟動dfs 服務start-dfs.sh
- 啟動hive 資料倉庫服務 hive --service metastore >metastore.log 2>& 1&
- 啟動spark服務start-all.sh
- 啟動sparkshell ./spark-shell –master spark://master:7077
3)案例實戰
- Spark on hive 實戰在spark-shell 模式下
val hiveContext=new org.apache.spark.sql.hive.HiveContext(sc)
hiveContext.sql("use hive")//使用hive 資料庫
hiveContext.sql("show tables").collect.foreach(println)// 查詢資料庫中的表
hiveContext.sql("select count(*) from sogouq1").collect.foreach(println)//(注意此時使用的是spark的引擎)
hiveContext.sql(“select count(*)from sogouq2 where website like '%baidu%'”).collect.foreach(println)
hiveContext.sql(“select count