【版權聲明:本指南爲廈門大學林子雨開設的《大數據技術原理與應用》課程新增配套學習資料,版權所有,轉載請註明出處,請勿用於商業用途】
本指南介紹了Hive,並詳細指引讀者安裝Hive。 前面第幾章學習指南已經指導大家安裝Linux操作系統,並安裝配置了Hadoop,但是這隻表明我們已經安裝好了Hadoop分佈式文件系統,而Hive需要另外下載安裝,本指南就是詳細指導大家安裝並配置Hive,完成後大家可以結合廈門大學林子雨開設的《大數據技術原理與應用》課程第14章節進行深入學習。
一、Hive簡介
Hive是Facebook開發的構建於Hadoop集羣之上的數據倉庫應用,可以將結構化的數據文件映射爲一張數據庫表,並提供完整的SQL查詢功能,可以將SQL語句轉換爲MapReduce任務進行運行。
Hive是一個可以提供有效的、合理的且直觀的組織和使用數據的模型,即使對於經驗豐富的Java開發工程師來說,將這些常見的數據運算對應到底層的MapReduce Java API也是令人敬畏的。Hive可以幫用戶做這些工作,用戶就可以集中精力關注查詢本身了。Hive可以將大多數的查詢轉換爲MapReduce任務。Hive最適合於數據倉庫應用程序,使用該應用程序進行相關的靜態數據分析,不需要快速響應給出結果,而且數據本身也不會頻繁變化。
Hive不是一個完整的數據庫。Hadoop以及HDFS的設計本身約束和侷限性限制了Hive所能勝任的工作。最大的限制就是Hive不支持記錄級別的更新、插入或者刪除。用戶可以通過查詢生成新表或將查詢結果導入到文件中去。因爲,Hadoop是一個面向批處理的系統,而MapReduce啓動任務啓動過程需要消耗很長時間,所以Hive延時也比較長。Hive還不支持事務。因此,Hive不支持聯機事務處理(OLTP),更接近於一個聯機分析技術(OLAP)工具,但是,目前還沒有滿足“聯機”部分。
Hive提供了一系列的工具,可以用來進行數據提取轉化加載(ETL),其中,ETL是一種可以存儲、查詢和分析存儲在Hadoop中的大規模數據的機制。因此,Hive是最適合數據倉庫應用程序的,它可以維護海量數據,而且可以對數據進行挖掘,然後形成意見和報告等。
因爲大多數的數據倉庫應用程序是基於SQL的關係數據庫現實的,所以,Hive降低了將這些應用程序移植到Hadoop上的障礙。如果用戶懂得SQL,那麼學習使用Hive會很容易。因爲Hive定義了簡單的類SQL 查詢語言——HiveQL,這裏值得一提的是,與SQLServer、Oracle相比,HiveQL和MySQL提供的SQL語言更接近。同樣的,相對於其他的Hadoop語言和工具來說,Hive也使得開發者將基於SQL的應用程序移植到Hadoop變得更加容易。
二、Hive安裝
因爲Hive是構建在Hadoop之上的,所以在安裝Hive前,我們需要安裝Hadoop環境。Hadoop的安裝可以參照廈門大學數據庫實驗室網站上的安裝教程(http://dblab.xmu.edu.cn/blog/install-hadoop/-simplify),但是,請注意,在按照該教程安裝完Hadoop以後,不要進行配置,Hadoop的配置過程,稍後我們在安裝完Hive後一起進行。
下面開始安裝Hive。
安裝Hive的過程和安裝Hadoop很類似,首先,我們先下載一個Hive軟件壓縮包(下載地址:http://www.apache.org/dyn/closer.cgi/hive/),然後進行解壓縮,具體如下:
- cd ~/下載
- sudo tar -zxvf ./apache-hive-1.2.1-bin.tar.gz -C /usr/local # 解壓到/usr/local中
- cd /usr/local/
- sudo mv ./apache-hive-1.2.1-bin/ ./hive # 將文件夾名改爲hive
- sudo chown -R hadoop:hadoop ./hive # 修改文件權限
- sudo mkdir -p /usr/local/hive/warehouse # 創建元數據存儲文件夾
- sudo chmod a+rwx /usr/local/hive/warehouse # 修改文件權限
爲了方便使用,我們把hive命令加入到環境變量中去,需要使用以下命令編輯.bashrc文件:
- vim ~/.bashrc # 設置環境變量
進入.bashrc編輯狀態以後,需要在文件最前面添加如下幾行:
export HIVE_HOME=/usr/local/hive
export PATH=$PATH:$HIVE_HOME/bin
完成上述操作後,需要運行以下命令讓配置生效:
- source ~/.bashrc # 使配置立即生效
然後運行hive命令啓動Hive,命令如下:
- hive # 啓動Hive
當出現以下界面即爲啓動成功。
若啓動不成功,則會出現以下錯誤:
則需要進入到hadoop安裝目錄下的share/hadoop/yarn/lib下刪除jline-0.9.94.jar文件,再啓動hive即可(因爲高版本的Hadoop對Hive有捆綁)。
三、 Hive配置
通過Hadoop的學習我們已經知道,Hadoop的運行模式有三種:本地模式、僞分佈式模式和分佈式模式。這裏我們以介紹本地模式爲主,其他模式只進行簡單介紹。因爲,本地模式是Hadoop的默認模式,所以,Hadoop不需要進行其他配置,我們只需對Hive進行相應配置。這裏只需修改hive-site.xml文件,如果該文件不存在,用戶需要自己新建一個。(注意:在$HIVE_HOME/conf目錄下我們可能會看到hive-default.xml.template這個大文件,這個文件中包含了Hive提供的配置屬性以及默認的屬性值,這些屬性中的絕大多數,用戶可以忽略不管)。
在安裝Hive時,默認情況下,元數據存儲在Derby數據庫中。Derby是一個完全用Java編寫的數據庫,所以可以跨平臺,但需要在JVM中運行 。因爲多用戶和系統可能需要併發訪問元數據存儲,所以默認的內置數據庫並不適用於生產環境。任何一個適用於JDBC進行連接的數據庫都可用作元數據庫存儲,這裏我們把MySQL作爲存儲元數據的數據庫。接下來,我們分別對這兩種方式進行介紹,即使用Derby數據庫的方式和使用MySQL數據庫的方式。
使用Derby數據庫的方式
本地模式中,用戶的“表”等元數據信息,都默認存儲在file://user/hive/warehouse,對於其他模式默認存儲路徑是hdfs://namenode_server/user/hive/warehouse。使用如下命令編輯hive-site.xml文件:
- vim /usr/local/hive/conf/hive-site.xml
在hive-site.xml文件添加以下內容:
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
- <configuration>
- <property>
- <name>hive.metastore.warehouse.dir</name>
- <value>/usr/local/hive/warehouse</value>
- <description>location of default database for the warehouse</description>
- </property>
- <property>
- <name>javax.jdo.option.ConnectionURL</name>
- <value>jdbc:derby:;databaseName=/usr/local/hive/metastore_db;create=true</value>
- <description>JDBC connect string for a JDBC metastore</description>
- </property>
- </configuration>
僞分佈式模式和分佈式模式配置Hive,只需根據Hadoop配置文件core-site.xml中fs.defaultFS的值對hive.metastore.warehouse.dir 進行相應修改即可。這裏對Hadoop的模式配置,可以參考廈門大學數據庫實驗室網站上的的配置教程(http://dblab.xmu.edu.cn/blog/install-hadoop-simplify)
Hive配置完成後,下面來啓動它,並使用簡單的HiveQL命令進行相應測試。我們先新建了一個表x,它有1個int型屬性a,然後查找表x中的所有屬性,最後刪除表x,然後退出。HiveQL命令與SQL命令很相似,所以,讀者如果有SQL基礎的話,會很快上手。關於HiveQL命令的使用方法會在第4節詳細介紹。
注意,命令最後需要以分號“;”結束。
使用MySQL數據庫的方式
1)首先我們需要安裝MySQL(如果本機上已經安裝MySQL,請跳過此步驟)。可以參考網址(http://dev.mysql.com/downloads/mysql/)進行下載安裝,也可以用apt-get 命令下載,這裏我們選擇後者。
a.查看並卸載系統自帶的MySQL相關安裝包,命令如下:
- rpm -qa|grep mysql
若沒有安裝rpm工具,系統會有提示,按照提示安裝即可。接下來查看是否有系統自帶的MySQL相關安裝包,若有,按下面命令刪除:
- sudo rpm -e --nodeps mysql-libs-xxxxxx
b.安裝MySQL,命令如下:
- sudo apt-get install mysql-server
c. 啓動設置MySQL,命令如下:
- sudo service mysql start #啓動mysql服務
- sudo chkconfig mysql on #設置爲開機自啓動
- sudo /usr/bin/mysqladmin -u root password '123' #設置root用戶登錄密碼
- mysql -u root -p #登錄mysql
d. 創建hive用戶,數據庫等,命令如下:
- insert into mysql.user (Host,User,Password) values ("localhost","hive",password (" hive")); # 創建hive用戶
- create database hive; # 創建hive數據庫
- grant all on hive.* to hive@'%' identified by 'hive';
- grant all on hive.* to hive@'localhost' identified by 'hive';
- flush privileges;
- exit #退出mysql
- mysql -u hive -p hive #驗證hive用戶
- show databases;
看到以下信息,則說明創建成功。
2)配置Hive,修改hive-site.xml文件,修改後的結果如下:
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
- <configuration>
- <property>
- <name>hive.metastore.warehouse.dir</name>
- <value>/usr/local/hive/warehouse</value>
- <description>location of default database for the warehouse</description>
- </property>
- <property>
- <name>javax.jdo.option.ConnectionURL</name>
- <value>jdbc:mysql://localhost:3306/hive;createDatebaseIfNotExist=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.ConnectionPassword </name>
- <value>hive </value>
- </property>
- <property>
- <name>javax.jdo.option.ConnectionUserName</name>
- <value>hive</value>
- <description>Username to use against metastore database</description>
- </property>
- </configuration>
修改完hive-site.xml文件後,我們需要把JDBC驅動放置在lib目錄下(JDBC驅動程序mysql-connector-java-x.x.x-bin.jar文件的下載地址爲http://www.mysql.com/downloads/connector/j/ ),命令如下:
- mv ~/下載/mysql-connector-java-5.1.30-bin.jar /usr/local/hive /lib/ #拷貝mysql-connector-java-5.1.30-bin.jar 到hive 的lib下
- cp /usr/local/hive/lib/jline-2.12.jar /usr/local/hadoop /share/ hadoop/yarn/lib # 把jline-2.12.jar拷貝到hadoop相應目錄下
- mkdir -p /usr/local/hive/tmp #創建hive臨時文件夾
- sudo chmod a+rwx /usr/local/hive/tmp # 修改文件權限
接下來,啓動測試Hive。首先啓動Hadoop後,執行Hive命令 hive
,並輸入 show
databases;
進行測試。
hive client常用命令可以通過 hive --help
查看。下面再介紹一些hive
client常用命令,用戶可以自行測試:
- show tables; #查看所有表名
- show tables 'ad*' ; #查看以'ad'開頭的表名
- set 命令 #設置變量與查看變量
- set –v; #查看所有的變量
- set hive.stats.atomic; #查看hive.stats.atomic變量
- set hive.stats.atomic=false; #設置hive.stats.atomic變量
- dfs -ls ; #查看hadoop所有文件路徑
- dfs -ls /usr/local/hive/warehouse/; #查看hive所有文件
- source file <filepath> #在client裏執行一個hive腳本文件
- quit; #退出交互式shell
- exit #退出交互式shell
- reset #重置配置爲默認值
- !ls #從Hive shell執行一個shell命令
四、Hive的常用HiveQL操作
1)Hive基本數據類型
首先,我們簡單敘述一下HiveQL的基本數據類型。
Hive支持基本數據類型和複雜類型, 基本數據類型主要有數值類型(INT、FLOAT、DOUBLE ) 、布爾型和字符串, 複雜類型有三種:ARRAY、MAP 和 STRUCT。
a.基本數據類型
- TINYINT: 1個字節
- SMALLINT: 2個字節
- INT: 4個字節
- BIGINT: 8個字節
- BOOLEAN: TRUE/FALSE
- FLOAT: 4個字節,單精度浮點型
- DOUBLE: 8個字節,雙精度浮點型STRING 字符串
b.複雜數據類型
- ARRAY: 有序字段
- MAP: 無序字段
- STRUCT: 一組命名的字段
2)常用的HiveQL操作命令
Hive常用的HiveQL操作命令主要包括:數據定義、數據操作。接下來詳細介紹一下這些命令即用法(想要了解更多請參照《Hive編程指南》一書)。
a.數據定義:主要用於創建修改和刪除數據庫、表、視圖、函數和索引。
創建、修改和刪除數據庫
- create database if not exists hive; #創建數據庫
- show databases; #查看Hive中包含數據庫
- show databases like 'h.*'; #查看Hive中以h開頭數據庫
- describe databases; #查看hive數據庫位置等信息
- alter database hive set dbproperties; #爲hive設置鍵值對屬性
- use hive; #切換到hive數據庫下
- drop database if exists hive; #刪除不含表的數據庫
- drop database if exists hive cascade; #刪除數據庫和它中的表
注意,除 dbproperties屬性外,數據庫的元數據信息都是不可更改的,包括數據庫名和數據庫所在的目錄位置,沒有辦法刪除或重置數據庫屬性。
創建、修改和刪除表
- #創建內部表(管理表)
- create table if not exists hive.usr(
- name string comment 'username',
- pwd string comment 'password',
- address struct<street:string,city:string,state:string,zip:int>,
- comment 'home address',
- identify map<int,tinyint> comment 'number,sex')
- comment 'description of the table'
- tblproperties('creator'='me','time'='2016.1.1');
- #創建外部表
- create external table if not exists usr2(
- name string,
- pwd string,
- address struct<street:string,city:string,state:string,zip:int>,
- identify map<int,tinyint>)
- row format delimited fields terminated by ','
- location '/usr/local/hive/warehouse/hive.db/usr';
- #創建分區表
- create table if not exists usr3(
- name string,
- pwd string,
- address struct<street:string,city:string,state:string,zip:int>,
- identify map<int,tinyint>)
- partitioned by(city string,state string);
- #複製usr表的表模式
- create table if not exists hive.usr1 like hive.usr;
-
- show tables in hive;
- show tables 'u.*'; #查看hive中以u開頭的表
- describe hive.usr; #查看usr表相關信息
- alter table usr rename to custom; #重命名錶
-
- #爲表增加一個分區
- alter table usr2 add if not exists
- partition(city=”beijing”,state=”China”)
- location '/usr/local/hive/warehouse/usr2/China/beijing';
- #修改分區路徑
- alter table usr2 partition(city=”beijing”,state=”China”)
- set location '/usr/local/hive/warehouse/usr2/CH/beijing';
- #刪除分區
- alter table usr2 drop if exists partition(city=”beijing”,state=”China”)
- #修改列信息
- alter table usr change column pwd password string after address;
-
- alter table usr add columns(hobby string); #增加列
- alter table usr replace columns(uname string); #刪除替換列
- alter table usr set tblproperties('creator'='liming'); #修改表屬性
- alter table usr2 partition(city=”beijing”,state=”China”) #修改存儲屬性
- set fileformat sequencefile;
- use hive; #切換到hive數據庫下
- drop table if exists usr1; #刪除表
- drop database if exists hive cascade; #刪除數據庫和它中的表
視圖和索引的創建、修改和刪除
主要語法如下,用戶可自行實現。
- create view view_name as....; #創建視圖
- alter view view_name set tblproperties(…); #修改視圖
因爲視圖是隻讀的,所以 對於視圖只允許改變元數據中的 tblproperties屬性。
- #刪除視圖
- drop view if exists view_name;
- #創建索引
- create index index_name on table table_name(partition_name/column_name)
- as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild....;
這裏’org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler’是一個索引處理器,即一個實現了索引接口的Java類,另外Hive還有其他的索引實現。
- alter index index_name on table table_name partition(...) rebulid; #重建索引
如果使用 deferred rebuild,那麼新索引成空白狀態,任何時候可以進行第一次索引創建或重建。
- show formatted index on table_name; #顯示索引
- drop index if exists index_name on table table_name; #刪除索引
用戶自定義函數
在新建用戶自定義函數(UDF)方法前,先了解一下Hive自帶的那些函數。show functions;
命令會顯示Hive中所有的函數名稱:
若想要查看具體函數使用方法可使用describe function 函數名:
首先編寫自己的UDF前需要繼承UDF類並實現evaluate()函數,或是繼承GenericUDF類實現initialize()函數、evaluate()函數和getDisplayString()函數,還有其他的實現方法,感興趣的用戶可以自行學習。
另外,如果用戶想在Hive中使用該UDF需要將我們編寫的Java代碼進行編譯,然後將編譯後的UDF二進制類文件(.class文件)打包成一個JAR文件,然後在Hive會話中將這個JAR文件加入到類路徑下,在通過create function語句定義好使用這個Java類的函數。
- add jar <jar文件的絕對路徑>; #創建函數
- create temporary function function_name;
- drop temporary function if exists function_name; #刪除函數
3)數據操作
主要實現的是將數據裝載到表中(或是從表中導出),並進行相應查詢操作,對熟悉SQL語言的用戶應該不會陌生。
向表中裝載數據
這裏我們以只有兩個屬性的簡單表爲例來介紹。首先創建表stu和course,stu有兩個屬性id與name,course有兩個屬性cid與sid。
- create table if not exists hive.stu(id int,name string)
- row format delimited fields terminated by '\t';
- create table if not exists hive.course(cid int,sid int)
- row format delimited fields terminated by '\t';
向表中裝載數據有兩種方法:從文件中導入和通過查詢語句插入。
a.從文件中導入
假如這個表中的記錄存儲於文件stu.txt中,該文件的存儲路徑爲usr/local/hadoop/examples/stu.txt,內容如下。
stu.txt:
1 xiapi
2 xiaoxue
3 qingqing
下面我們把這個文件中的數據裝載到表stu中,操作如下:
- load data local inpath '/usr/local/hadoop/examples/stu.txt' overwrite into table stu;
如果stu.txt文件存儲在HDFS 上,則不需要 local 關鍵字。
b.通過查詢語句插入
使用如下命令,創建stu1表,它和stu表屬性相同,我們要把從stu表中查詢得到的數據插入到stu1中:
- create table stu1 as select id,name from stu;
上面是創建表,並直接向新表插入數據;若表已經存在,向表中插入數據需執行以下命令:
- insert overwrite table stu1 select id,name from stu where(條件);
這裏關鍵字overwrite的作用是替換掉表(或分區)中原有數據,換成into關鍵字,直接追加到原有內容後。
從表中導出數據
a.可以簡單拷貝文件或文件夾
命令如下:
- hadoop fs -cp source_path target_path;
b.寫入臨時文件
命令如下:
- insert overwrite local directory '/usr/local/hadoop/tmp/stu' select id,name from stu;
查詢操作
和SQL的查詢完全一樣,這裏不再贅述。主要使用select…from…where…等語句,再結合關鍵字group by、having、like、rlike等操作。這裏我們簡單介紹一下SQL中沒有的case…when…then…句式、join操作和子查詢操作。
case…when…then…句式和if條件語句類似,用於處理單個列的查詢結果,語句如下:
- select id,name,
- case
- when id=1 then 'first'
- when id=2 then 'second'
- else 'third'
結果如下:
連接
連接(join)是將兩個表中在共同數據項上相互匹配的那些行合併起來, HiveQL 的連接分爲內連接、左向外連接、右向外連接、全外連接和半連接 5 種。
a. 內連接(等值連接)
內連接使用比較運算符根據每個表共有的列的值匹配兩個表中的行。
首先,我們先把以下內容插入到course表中(自行完成)。
1 3
2 1
3 1
下面, 查詢stu和course表中學號相同的所有行,命令如下:
- select stu.*, course.* from stu join course on(stu .id=course .sid);
執行結果如下:
b. 左連接
左連接的結果集包括“LEFT OUTER”子句中指定的左表的所有行, 而不僅僅是連接列所匹配的行。如果左表的某行在右表中沒有匹配行, 則在相關聯的結果集中右表的所有選擇列均爲空值,命令如下:
- select stu.*, course.* from stu left outer join course on(stu .id=course .sid);
執行結果如下:
c. 右連接
右連接是左向外連接的反向連接,將返回右表的所有行。如果右表的某行在左表中沒有匹配行,則將爲左表返回空值。命令如下:
- select stu.*, course.* from stu right outer join course on(stu .id=course .sid);
執行結果如下:
d. 全連接
全連接返回左表和右表中的所有行。當某行在另一表中沒有匹配行時,則另一個表的選擇列表包含空值。如果表之間有匹配行,則整個結果集包含基表的數據值。命令如下:
- select stu.*, course.* from stu full outer join course on(stu .id=course .sid);
執行結果如下:
e. 半連接
半連接是 Hive 所特有的, Hive 不支持 in 操作,但是擁有替代的方案; left semi join, 稱爲半連接, 需要注意的是連接的表不能在查詢的列中,只能出現在 on 子句中。命令如下:
- select stu.* from stu left semi join course on(stu .id=course .sid);
執行結果如下:
子查詢
標準 SQL 的子查詢支持嵌套的 select 子句,HiveQL 對子查詢的支持很有限,只能在from 引導的子句中出現子查詢。
注意,在定義或是操作表時,不要忘記指定所需數據庫。
五、Hive簡單編程實踐
下面我們以詞頻統計算法爲例,來介紹怎麼在具體應用中使用Hive。詞頻統計算法又是最能體現MapReduce思想的算法之一,這裏我們可以對比它在MapReduce中的實現,來說明使用Hive後的優勢。
MapReduce實現詞頻統計的代碼可以通過下載Hadoop源碼後,在 $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.1.jar 包中找到(wordcount類),wordcount類由63行Java代碼編寫而成。下面首先簡單介紹一下怎麼使用MapReduce中wordcount類來統計單詞出現的次數,具體步驟如下:
1)創建input目錄,output目錄會自動生成。其中input爲輸入目錄,output目錄爲輸出目錄。命令如下:
- cd /usr/local/hadoop
- mkdir input
2)然後,在input文件夾中創建兩個測試文件file1.txt和file2.txt,命令如下:
- cd /usr/local/hadoop/input
- echo "hello world" > file1.txt
- echo "hello hadoop" > file2.txt
3)執行如下hadoop命令:
- cd ..
- hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.4.1.jar wordcount input output
4)我們可以到output文件夾中查看結果,結果如下:
下面我們通過HiveQL實現詞頻統計功能,此時只要編寫下面7行代碼,而且不需要進行編譯生成jar來執行。HiveQL實現命令如下:
- create table docs(line string);
- load data inpath 'input' overwrite into table docs;
- create table word_count as
- select word, count(1) as count from
- (select explode(split(line,' '))as word from docs) w
- group by word
- order by word;
執行後,用select語句查看,結果如下:
由上可知,採用Hive實現最大的優勢是,對於非程序員,不用學習編寫Java MapReduce代碼了,只需要用戶學習使用HiveQL就可以了,而這對於有SQL基礎的用戶而言是非常容易的。