apache hive 使用概述
2019獨角獸企業重金招聘Python工程師標準>>>
1???????? 產品概述
1.1? 產品功能
????????Apache Hive數據倉庫軟件提供對存儲在分布式中的大型數據集的查詢和管理,它本身是建立在Apache Hadoop之上,主要提供以下功能:
1. 它提供了一系列的工具,可用來對數據進行提取/轉化/加載(ETL);是一種可以存儲、查詢和分析存儲在HDFS(或者HBase)中的大規模數據的機制;查詢是通過MapReduce來完成的(并不是所有的查詢都需要MapReduce來完成,比如select * from XXX就不需要;在Hive0.11對類似select a,b from XXX的查詢通過配置也可以不通過MapReduce來完成);
2. Hive是一種建立在Hadoop文件系統上的數據倉庫架構,并對存儲在HDFS中的數據進行分析和管理;
3. Hive定義了一種類似SQL的查詢語言,被稱為HQL,對于熟悉SQL的用戶可以直接利用Hive來查詢數據。同時,這個語言也允許熟悉MapReduce開發者們開發自定義的mappers和reducers來處理內建的mappers和reducers無法完成的復雜的分析工作。Hive可以允許用戶編寫自己定義的函數UDF,在查詢中使用。Hive中有3種UDF:User Defined Functions(UDF)、User Defined Aggregation Functions(UDAF)、User Defined Table Generating Functions(UDTF)。
????現在,Hive已經是一個成功的Apache項目,很多組織把它用作一個通用的、可伸縮的數據處理平臺。
????????Hive和傳統的關系型數據庫有很大的區別,Hive將外部的任務解析成一個MapReduce可執行計劃,而啟動MapReduce是一個高延遲的一件事,每次提交任務和執行任務都需要消耗很多時間,這也就決定Hive只能處理一些高延遲的應用(如果想處理低延遲的應用,可以考慮一下Hbase)。同時,由于設計的目標不一樣,Hive目前還不支持事務;不能對表數據進行修改。
1.2? Hive和傳統數據庫進行比較
????????Hive在很多方面和RMDB類似,比如說它支持SQL接口;但是由于其它底層設計的原因,對HDFS和Mapreduce有很強的依賴,這也就意味這Hive的體系結構和RMDB有很大的區別。這些區別又間接的影響到Hive所支持的一些特性。
????在傳統的RMDB中,表的模式是在數據加載的時候強行確定好的。如果在加載時發現數據不符合模式,則拒絕加載這些數據。而Hive在加載的過程中不對數據進行任何的驗證操作,其只是簡單的將數據復制或者移動到表對應的目錄下面。從這方面來說,傳統數據庫在數據加載的過程中比Hive要慢。但是因為傳統數據庫在數據加載過程中可以進行一些處理,比如對某一列建立索引等,這樣可以提升數據的查詢性能。而在這方面Hive不行。
比較項 | SQL | HiveQL |
ANSI SQL | 支持 | 不完全支持 |
更新 | UPDATE\INSERT\DELETE | insert OVERWRITE\INTO TABLE |
事務 | 支持 | 不支持 |
模式 | 寫模式 | 讀模式 |
數據保存 | 塊設備、本地文件系統 | HDFS |
延時 | 低 | 高 |
多表插入 | 不支持 | 支持 |
子查詢 | 完全支持 | 只能用在From子句中 |
視圖 | Updatable | Read-only |
可擴展性 | 低 | 高 |
數據規模 | 小 | 大 |
…… | …… | …… |
????從上表可以看出,Hive和傳統的數據庫還是有很多的區別。
????????Hive的SQL方言一般被稱為HiveQL,在下文我們簡稱HQL。在上面我們提到,HQL并不完全支持SQL92標準。這個也是有原因的。遵循SQL92從Hive的設計開始就不是它的目標。
1.3?應用場景
????????Hive目前主要應用在海量數據處理、數據挖掘、數據分析等方面,hive是針批量對長時間數據分析設計的,不能做交互式的實時查詢。
2???????? 產品架構
????????Hive產品架構如下圖所示:
????????Hive架構圖中涉及服務、元數據、Hdfs、Mapreduce等信息,下面分別進行說明:
2.1? 服務
????????hive有三種service,分別是cli,hiveserver和hwi。
1. cli是命令行工具,為默認服務,啟動方式$HIVE_HOME/bin/hive 或 $HIVE_HOME/bin/hive --service cli。
2. hiverserver通過thrift對外提供服務,默認端口10000,啟動方式為$HIVE_HOME/bin/hive--service hiveserver。
3. hwi為web接口,可以通過瀏覽器訪問hive,默認端口9999,啟動方式為$HIVE_HOME/bin/hive--service hwi。
????每個服務間互相獨立,有各自的配置文件(配置metasotre/namenode/jobtracker等),如果metasotre的配置一樣則物理上對應同一hive庫。
????????Driver用于解釋、編譯、優化、執行HQL,每個service的Driver相互獨立。
????????CLI為用戶提供命令行接口,每個CLI獨享配置,即在一個CLI里修改配置不影響別的CLI。
多個JDBC可同時連到同一HiveServer上,所有會話共享一份配置。(注:從0.9.0起hiveserver配置已經從global降為session,即每個session的配置相互獨立)
?????多個瀏覽器可同時連到同一HWI上,所有會話共享一份配置。
????????Hive可以在運行時用–service選項來明確指定使用的服務類型,可以用下面的--service help來查看幫助,如下:
[wyp@master ~]$ hive --service help
Usage ./hive <parameters> --service serviceName <service parameters>
Service List: beeline cli help hiveserver2 hiveserver hwi jar lineage metastore metatool orcfiledump rcfilecat
Parameters parsed:
? --auxpath : Auxillary jars
? --config : Hive configuration directory
? --service : Starts specific service/component. cli is default
Parameters used:
? HADOOP_HOME or HADOOP_PREFIX : Hadoop install directory
? HIVE_OPT : Hive options
For help on a particular service:
? ./hive --service serviceName --help
Debug help:? ./hive --debug –help
????上面的輸出項Service List,里面顯示出Hive支持的服務列表:beeline cli help hiveserver2 hiveserver hwi jar lineage metastore metatool orcfiledump rcfilecat,下面介紹最常用的一些服務。
(1)cli:這個就是Command Line Interface的簡寫,是Hive的命令行界面,用的比較多。這是默認的服務,直接可以在命令行里面使用。
(2)hiveserver:這個可以讓Hive以提供Trift服務的服務器形式來運行,允許許多不同語言編寫的客戶端進行通信。使用時需要啟動HiveServer服務以和客戶端聯系,可以通過設置HIVE_PORT環境變量來設置服務器所監聽的端口號,在默認的情況下,端口為10000。可以通過下面方式來啟動hiveserver:
[wyp@master ~]$? bin/hive --service hiveserver -p 10002
Starting Hive Thrift Server
其中-p參數也是用來指定監聽端口的。
(3)hwi:其實就是hive web interface的縮寫,它是Hive的Web接口,是hive cli的一個web替換方案。
(4)jar:與Hadoop jar等價的Hive的接口,這是運行類路徑中同時包含Hadoop和Hive類的Java應用程序的簡便方式。
(5)metastore:在默認情況下,metastore和Hive服務運行在同一個進程中。使用這個服務,可以讓metastore作為一個單獨的進程運行,可以通過METASTORE_PORT來指定監聽的端口號,具體如下圖所示:
2.2??元數據
????????Hive的數據分為表數據和元數據,表數據是Hive中表格(table)具有的數據;而元數據是用來存儲表的名字,表的列和分區及其屬性(是否為外部表等),表的數據所在目錄等。
????元數據位置通過參數javax.jdo.option.ConnectionURL來指定,可在會話中自由修改。相關的參數包括:
javax.jdo.option.ConnectionDriverName??? ?????? #數據庫驅動
javax.jdo.option.ConnectionURL ?????? ?????? ?????? #數據庫ip端口庫名等
javax.jdo.option.ConnectionUserName?????? ?????? #用戶名
javax.jdo.option.ConnectionPassword ?????? ?????? #密碼
通過修改這些參數可以在多個MetaStore間熱切換,可用于HA。
2.3??NameNode與JobTracker
????????NameNode由fs.default.name指定,JobTracker由mapred.job.tracker指定,這兩個參數都可以在會話中自由修改來指向不同的NameNode和JobTracker。
????配合MetaStore可以有多種組合出現,例如在同一個MetaStore里讓table1的數據存在HDFS1,用JobTracker1計算,table2的數據存在HDFS2,用JobTracker2計算,或者讓兩個表都在JobTracker3上計算。
????????NameNode和JobTracker最好指向同一個集群,否則計算的時候需要跨集群復制數據。
????在MetaStore存儲的是表數據文件的絕對路徑,當心其與NameNode/ JobTracker不在同一個集群里導致跨集群復制。
????對hiveserver與hwi配置的修改會作用到同一service上的所有會話。(注:從0.9.0起hiveserver配置已經從global降為session,即每個session的配置相互獨立)。
3 ? ? ? ??安裝部署
????????Hive最新版本是apache-hive-0.13.1-bin.tar.gz,下載地址為http://apache.fayea.com/apache-mirror/hive/hive-0.13.1/。
????下載后,選個目錄,解壓,命令如下:
# tar -zxvf hive-0.10.0.tar.gz
????現在需要配置Hive,才能夠運行Hive。進入conf文件夾,將hive-default.xml.template文件的內容復制到hive-site.xml文件中,操作如下:
#cd conf/
#cp hive-default.xml.template hive-site.xml
????在hive-site.xml文件中進行如下配置:
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/home/wyp/cloud/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_hdp?characterEncoding=UTF-8&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>123456</value>
<description>password to use against metastore database</description>
</property>
????????Hive將元數據存儲在RDBMS中,比如MySQL、Derby中。Hive默認是用Derby數據庫,這里修改為MySQL(所以要確保電腦上已經安裝好了MySQL數據庫)。需要將mysql驅動jar包mysql-connector-java-5.1.22-bin.jar拷貝到$HIVE_HOME/lib/目錄下。然后編輯/etc/profile文件,將Hive的home目錄添加進去,操作如下:
#sudo vim /etc/profile
????在其中添加下面語句,修改Hive的home路徑為解壓的目錄:
export HIVE_HOME=/home/...hive-0.10.0
PATH=$PATH:$HIVE_HOME/bin
????最后讓上面的修改生效,請運行下面的命令:
#source /etc/profile
????現在可以試一下,hive是否安裝好(需要啟動Hadoop,否則不能運行成功!):
#hive
hive>
????如果出現了上述情況,說明hive安裝成功。
4? ? ? ? ?數據存儲模式
1. Hive的數據存儲
????????Hive是基于Hadoop分布式文件系統的,它的數據存儲在Hadoop分布式文件系統中。Hive本身是沒有專門的數據存儲格式,也沒有為數據建立索引,只需要在創建表的時候告訴Hive數據中的列分隔符和行分隔符,Hive就可以解析數據。所以往Hive表里面導入數據只是簡單的將數據移動到表所在的目錄中(如果數據是在HDFS上;但如果數據是在本地文件系統中,那么是將數據復制到表所在的目錄中)。
????????Hive中主要包含以下幾種數據模型:Table(表),External Table(外部表),Partition(分區),Bucket(桶)。
a. 表: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表所有的數據都存放在這個目錄中。這個例外是外部表。
b.外部表:Hive中的外部表和表很類似,但是其數據不是放在自己表所屬的目錄中,而是存放到別處,這樣的好處是如果你要刪除這個外部表,該外部表所指向的數據是不會被刪除的,它只會刪除外部表對應的元數據;而如果你要刪除表,該表對應的所有數據包括元數據都會被刪除。
c.分區:在Hive中,表的每一個分區對應表下的相應目錄,所有分區的數據都是存儲在對應的目錄中。比如wyp表有dt和city兩個分區,則對應dt=20131218,city=BJ對應表的目錄為/user/hive/warehouse/dt=20131218/city=BJ,所有屬于這個分區的數據都存放在這個目錄中。
d.桶:對指定的列計算其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。
Hive數據抽象結構如下圖所示:
2.Hive的元數據
????????Hive中的元數據包括表的名字,表的列和分區及其屬性,表的屬性(是否為外部表等),表的數據所在目錄等。由于Hive的元數據需要不斷的更新、修改,而HDFS系統中的文件是多讀少改的,這顯然不能將Hive的元數據存儲在HDFS中。目前Hive將元數據存儲在數據庫中,如Mysql、Derby中。我們可以通過以下的配置來修改Hive元數據的存儲方式。
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost:3306/hive_hdp?characterEncoding=UTF-8
&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>123456</value>
<description>password to use against metastore database</description>
</property>
????還需要將連接對應數據庫的依賴包復制到${HIVE_HOME}/lib目錄中,這樣才能將元數據存儲在對應的數據庫中。
5 ? ? ? ?基本操作
5.1? Hive內置數據類型
????????Hive的內置數據類型可以分為兩大類:(1)基礎數據類型;(2)復雜數據類型。其中,基礎數據類型包括:TINYINT,SMALLINT,INT,BIGINT,BOOLEAN,FLOAT,DOUBLE,STRING,BINARY,TIMESTAMP,DECIMAL,CHAR,VARCHAR,DATE。下面的表格列出這些基礎類型所占的字節以及從什么版本開始支持這些類型。
數據類型 | 所占字節 | 開始支持版本 |
TINYINT | 1byte,-128 ~ 127 | |
SMALLINT | 2byte,-32,768 ~ 32,767? | |
INT | 4byte,-2,147,483,648 ~ ? 2,147,483,647 | |
BIGINT | 8byte,-9,223,372,036,854,775,808 ? ~ 9,223,372,036,854,775,807 | |
BOOLEAN | ||
FLOAT | 4byte雙精度 | |
DOUBLE | 8byte雙精度 | |
STRING | ||
BINARY | 從Hive0.8.0開始支持 | |
TIMESTAMP | 從Hive0.8.0開始支持 | |
DECIMAL | 從Hive0.11.0開始支持 | |
CHAR | 從Hive0.13.0開始支持 | |
VARCHAR | 從Hive0.12.0開始支持 | |
DATE | 從Hive0.12.0開始支持 |
復雜類型包括ARRAY,MAP,STRUCT,UNION,這些復雜類型是由基礎類型組成的。
ARRAY:ARRAY類型是由一系列相同數據類型的元素組成,這些元素可以通過下標來訪問。比如有一個ARRAY類型的變量fruits,它是由['apple','orange','mango']組成,那么我們可以通過fruits[1]來訪問元素orange,因為ARRAY類型的下標是從0開始的;
MAP:MAP包含key->value鍵值對,可以通過key來訪問元素。比如”userlist”是一個map類型,其中username是key,password是value;那么我們可以通過userlist['username']來得到這個用戶對應的password;
STRUCT:STRUCT可以包含不同數據類型的元素。這些元素可以通過”點語法”的方式來得到所需要的元素,比如user是一個STRUCT類型,那么可以通過user.address得到這個用戶的地址。
UNION: UNIONTYPE,他是從Hive 0.7.0開始支持的。
創建一個包含復制類型的表格可以如下:
CREATE TABLE employees (
??? name STRING,
??? salary FLOAT,
??? subordinates ARRAY<STRING>,
??? deductions MAP<STRING, FLOAT>,
??? address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>
) PARTITIONED BY (country STRING, state STRING);
5.2? Hive參數配置方法
????????Hive提供三種可以改變環境變量的方法,分別是:(1)修改${HIVE_HOME}/conf/hive-site.xml配置文件;(2)命令行參數;(3)在已經進入cli時進行參數聲明。下面分別介紹這幾種設定。
方法一:
????在Hive中,所有的默認配置都在${HIVE_HOME}/conf/hive-default.xml文件中,如果需要對默認的配置進行修改,可以創建一個hive-site.xml文件,放在${HIVE_HOME}/conf目錄下。里面可以對一些配置進行個性化設定。在hive-site.xml的格式如下:
<configuration>
??? <property>
??????? <name>hive.metastore.warehouse.dir</name>
??????? <value>/user/hive/warehouse</value>
??????? <description>location of
????????????? default database for the warehouse</description>
??? </property>
</configuration>
????所有的配置都是放在<configuration></configuration>標簽之間,一個configuration標簽里面可以存在多個<property></property>標簽。<name>標簽里面就是要設定屬性的名稱;<value>標簽里面是要設定的值;<description>標簽描述這個屬性的作用。絕大多少配置都是在xml文件里面配置的,因為在這里做的配置都全局用戶都生效,而且是永久的。用戶自定義配置會覆蓋默認配置。另外,Hive也會讀入Hadoop的配置,因為Hive是作為Hadoop的客戶端啟動的,Hive的配置會覆蓋Hadoop的配置。
方法二:
????在啟動Hive cli的時候進行配置,可以在命令行添加-hiveconf param=value來設定參數,例如:
# hive --hiveconf mapreduce.job.queuename=queue1
????這樣在Hive中所有MapReduce作業都提交到隊列queue1中。這一設定對本次啟動的會話有效,下次啟動需要重新配置。
方法三:
????在已經進入cli時進行參數聲明,可以在HQL中使用SET關鍵字設定參數,例如:
hive> set mapreduce.job.queuename=queue1;
????這樣也能達到方法二的效果。這種配置也是對本次啟動的會話有效,下次啟動需要重新配置。在HQL中使用SET關鍵字還可以查看配置的值,如下:
hive> set mapreduce.job.queuename;
mapreduce.job.queuename=queue1
????我們可以得到mapreduce.job.queuename=queue1。如果set后面什么都不添加,這樣可以查到Hive的所有屬性配置,如下:
hive> set;
datanucleus.autoCreateSchema=true
上述三種設定方式的優先級依次遞增。即參數聲明覆蓋命令行參數,命令行參數覆蓋配置文件設定。
5.3? Hive日志調試
????在很多程序中,可以通過輸出日志的形式來得到程序的運行情況,通過這些輸出日志來調試程序。
????在Hive中,使用的是Log4j來輸出日志,默認情況下,CLI是不能將日志信息輸出到控制臺的。在Hive0.13.0之前版本,默認的日志級別是WARN,從Hive0.13.0開始,默認的日志級別是INFO。默認的日志存放在/tmp/<user.name>文件夾的hive.log文件中,即/tmp/<user.name>/hive.log。
????在默認的日志級別情況下,不能將DEBUG信息輸出,這樣一來出現的各種詳細的錯誤信息是不能輸出的。但是可以通過以下兩種方式修改log4j輸出的日志級別,從而利用這些調試日志進行錯誤定位,具體做法如下:
# hive --hiveconf hive.root.logger=DEBUG,console
????或者在${HIVE_HOME}/conf/hive-log4j.properties文件中找到hive.root.logger屬性,并將其修改為下面的設置
hive.root.logger=DEBUG,console
????上面兩種方法的設置各有優劣,方法一的設定只是對本次會話有效,下次如果還想修改日志輸出級別需要重新設定,但是不是每時每刻都需要修改日志的輸出級別,所以在有時需要修改輸出的日志級別,有時不需要的時候可以用這種方法;方法二將日志輸出級別設定到文件中去了,這個設定是對所有的用戶都生效,而且每次使用HQL的時候都會輸出一大堆的日志,這種情況適合那些無時無刻都需要HQL的運行日志的用戶。
5.4? hiveQL插入語法
1. Insert基本語法格式為:
INSERT OVERWRITE TABLE tablename [PARTITON(partcol1=val1,partclo2=val2)]select_statement FROM from_statement
示例:insert overwrite table test_insert select * from test_table;
2. 對多個表進行插入操作:
FROM fromstatte
INSERT OVERWRITE TABLE tablename1 [PARTITON(partcol1=val1,partclo2=val2)]select_statement1
INSERT OVERWRITE TABLE tablename2 [PARTITON(partcol1=val1,partclo2=val2)]select_statement2
示例:
from test_table
insert overwrite table test_insert1
select key
insert overwrite table test_insert2
select value;
insert的時候,from子句即可以放在select子句后面,也可以放在 insert子句前面。
hive不支持用insert語句一條一條的進行插入操作,也不支持update操作。數據是以load的方式加載到建立好的表中。數據一旦導入就不可以修改。
3.通過查詢將數據保存到filesystem
INSERT OVERWRITE [LOCAL] DIRECTORY directory SELECT.... FROM .....
導入數據到本地目錄:
insert overwrite local directory '/home/zhangxin/hive' select * from test_insert1;
產生的文件會覆蓋指定目錄中的其他文件,即將目錄中已經存在的文件進行刪除。
導出數據到HDFS中:
insert overwrite directory '/user/zhangxin/export_test' select value from test_table;
同一個查詢結果可以同時插入到多個表或者多個目錄中:
from test_insert1
insert overwrite local directory '/home/zhangxin/hive' select *
insert overwrite directory '/user/zhangxin/export_test' select value;
Hive insert into語句的標準語法如下:
用法一:
INSERT OVERWRITE TABLE tablename1 [PARTITION \
(partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] \
select_statement1 FROM from_statement;
用法二:
INSERT INTO TABLE tablename1 [PARTITION \
(partcol1=val1, partcol2=val2 ...)] \
select_statement1 FROM from_statement;
舉例:
hive> insert into table cite
> select * from tt;
????這樣就會將tt表格里面的數據追加到cite表格里面。并且在cite數據存放目錄生成了一個新的數據文件,這個新文件是經過處理的,列之間的分割是cite表格的列分割符,而不是tt表格列的分隔符。
(1) 如果兩個表格的維度不一樣,將會插入錯誤:
hive> insert into table cite
> select * from cite_standby;
FAILED: SemanticException [Error 10044]: Line 1:18 Cannot insert into
target table because column number/types are different 'cite':
Table insclause-0 has 2 columns, but query has 1 columns.
????從上面錯誤提示看出,查詢的表格cite_standby只有一列,而目標表格(也就是需要插入數據的表格)有2列,由于列的數目不一樣,導致了上面的語句不能成功運行,我們需要保證查詢結果列的數目和需要插入數據表格的列數目一致,這樣才行。
(2) 在用extended關鍵字創建的表格上插入數據將會影響到其它的表格的數據,因為他們共享一份數據文件。
(3) 如果查詢出來的數據類型和插入表格對應的列數據類型不一致,將會進行轉換,但是不能保證轉換一定成功,比如如果查詢出來的數據類型為int,插入表格對應的列類型為string,可以通過轉換將int類型轉換為string類型;但是如果查詢出來的數據類型為string,插入表格對應的列類型為int,轉換過程可能出現錯誤,因為字母就不可以轉換為int,轉換失敗的數據將會為NULL。
(4) 可以將一個表查詢出來的數據插入到原表中:
hive> insert into table cite
> select * from cite;
結果就是相當于復制了一份cite表格中的數據。
(5) 和insert overwrite的區別:
hive> insert overwrite table cite
> select * from tt;
上面的語句將會用tt表格查詢到的數據覆蓋cite表格已經存在的數據。
5.5? hiveQL刪除語法
hiveQL刪除語法如下所示:
hive> TRUNCATE TABLE t;
這樣將會刪掉表格t關聯的所有數據,但會保留表和metadata的完整性。
5.6? hiveQL執行文件
Hive可以運行保存在文件里面的一條或多條的語句,只要用-f參數,一般情況下,保存這些Hive查詢語句的文件通常用.q或者.hql后綴名,但是這不是必須的,你也可以保存你想要的后綴名。假設test文件里面有一下的Hive查詢語句:
select * from p limit 10;
select count(*) from p;
那么我們可以用下面的命令來查詢:
#bin/hive -f test
........這里省略了一些輸出...........
OK
196 242 3?? 881250949?? 20131102??? jx
186 302 3?? 891717742?? 20131102??? jx
22? 377 1?? 878887116?? 20131102??? jx
244 51? 2?? 880606923?? 20131102??? jx
Time taken: 4.386 seconds, Fetched: 4 row(s)
........這里省略了一些輸出...........
OK
4
Time taken: 16.284 seconds, Fetched: 1 row(s)
如果你配置好了Hive shell的路徑,你可以用SOURCE命令來運行那個查詢文件:
[wyp@wyp hive-0.11.0-bin]$ hive
hive> source /home/.../test;
........這里省略了一些輸出...........
........這里省略了一些輸出...........
OK
196 242 3?? 881250949?? 20131102??? jx
186 302 3?? 891717742?? 20131102??? jx
22? 377 1?? 878887116?? 20131102??? jx
244 51? 2?? 880606923?? 20131102??? jx
Time taken: 4.386 seconds, Fetched: 4 row(s)
........這里省略了一些輸出...........
OK
4
Time taken: 16.284 seconds, Fetched: 1 row(s)
6 ? ? ? ??數據導入導出
6.1? Hive數據導入的方式
Hive目前有四種導入數據的方式:
(1)從本地文件系統中導入數據到Hive表;
(2)從HDFS上導入數據到Hive表;
(3)從別的表中查詢出相應的數據并導入到Hive表中;
(4)在創建表的時候通過從別的表中查詢出相應的記錄并插入到所創建的表中。
6.1.1??????????? 本地導入
先在Hive中建表,如下:
hive> create table wyp
???? > (id? int , name string,
???? > age? int , tel string)
???? > ROW FORMAT DELIMITED
???? > FIELDS TERMINATED BY '\t'
???? > STORED AS TEXTFILE;
OK
Time taken:? 2.832?? seconds
這個表很簡單,只有四個字段。本地文件系統中有個/home/wyp/wyp.txt文件,內容如下:
[wyp @master?? ~]$ cat wyp.txt
1??? wyp?????? ?????? 25?? 13188888888888
2??? test 30?? 13888888888888
3??? zs??? 34?? 899314121
wyp.txt文件中的數據列之間是使用\t分割的,可以通過下面的語句將這個文件里面的數據導入到wyp表里面,操作如下:
hive> load data local inpath? 'wyp.txt'?? into table wyp;
Copying data from file:/home/wyp/wyp.txt
Copying file: file:/home/wyp/wyp.txt
Loading data to table? default .wyp
Table? default .wyp stats:
[num_partitions:? 0 , num_files:? 1 , num_rows:? 0 , total_size:? 67 ]
OK
Time taken:? 5.967?? seconds
這樣就將wyp.txt里面的內容導入到wyp表里面去了,可以到wyp表的數據目錄下查看,如下命令:
hive> dfs -ls /user/hive/warehouse/wyp ;
Found? 1?? items
-rw-r--r-- 3?? wyp supergroup? 67?? 2014 - 02 - 19?? 18 : 23?? /hive/warehouse/wyp/wyp.txt
數據的確導入到wyp表里面去了。
和關系型數據庫不一樣,Hive現在還不支持在insert語句里面直接給出一組記錄的文字形式,也就是說,Hive并不支持INSERT INTO .... VALUES形式的語句。
6.1.2??????????? HDFS導入
從本地文件系統中將數據導入到Hive表的過程中,其實是先將數據臨時復制到HDFS的一個目錄下(典型的情況是復制到上傳用戶的HDFS home目錄下,比如/home/wyp/),然后再將數據從那個臨時目錄下移動(注意,這里說的是移動,不是復制!)到對應的Hive表的數據目錄里面。既然如此,那么Hive肯定支持將數據直接從HDFS上的一個目錄移動到相應Hive表的數據目錄下,假設有下面這個文件/home/wyp/add.txt,具體的操作如下:
[wyp@master /home/q/hadoop-2.2.0]$ bin/hadoop fs -cat /home/wyp/add.txt
5?????? wyp1??? 23????? 131212121212
6?????? wyp2??? 24????? 134535353535
7?????? wyp3??? 25????? 132453535353
8?????? wyp4??? 26????? 154243434355
上面是需要插入數據的內容,這個文件是存放在HDFS上/home/wyp目錄(和本地導入的不同,本地導入中提到的文件是存放在本地文件系統上)里面,可以通過下面的命令將這個文件里面的內容導入到Hive表中,具體操作如下:
hive> load data inpath '/home/wyp/add.txt' into table wyp;
Loading data to table default.wyp
Table default.wyp stats:
[num_partitions: 0, num_files: 2, num_rows: 0, total_size: 215]
OK
Time taken: 0.47 seconds
?
hive> select * from wyp;
OK
5?????? wyp1??? 23????? 131212121212
6?????? wyp2??? 24????? 134535353535
7?????? wyp3??? 25????? 132453535353
8?????? wyp4??? 26????? 154243434355
1?????? wyp???? 25????? 13188888888888
2?????? test??? 30????? 13888888888888
3??? ???zs????? 34????? 899314121
Time taken: 0.096 seconds, Fetched: 7 row(s)
從上面的執行結果可以看到,數據的確導入到wyp表中了!請注意load data inpath ‘/home/wyp/add.txt’ into table wyp;里面是沒有local這個單詞的,這個是和本地導入方式的區別。
6.1.3??????????? 別的表查詢導入
假設Hive中有test表,其建表語句如下所示:
hive> create table test(
??? > id int, name string
??? > ,tel string)
??? > partitioned by
??? > (age int)
??? > ROW FORMAT DELIMITED
??? > FIELDS TERMINATED BY '\t'
??? > STORED AS TEXTFILE;
OK
Time taken: 0.261 seconds
大體和wyp表的建表語句類似,只不過test表里面用age作為了分區字段。下面語句將wyp表中的查詢結果插入到test表中:
hive> insert into table test
??? > partition (age='25')
??? > select id, name, tel
??? > from wyp;
#################################################################
?????????? 這里輸出了一堆Mapreduce任務信息,這里省略
#################################################################
Total MapReduce CPU Time Spent: 1 seconds 310 msec
OK
Time taken: 19.125 seconds
hive> select * from test;
OK
5?????? wyp1??? 131212121212??? 25
6?????? wyp2??? 134535353535??? 25
7?????? wyp3??? 132453535353??? 25
8?????? wyp4??? 154243434355??? 25
1 ??????wyp???? 13188888888888? 25
2?????? test??? 13888888888888? 25
3?????? zs????? 899314121?????? 25
Time taken: 0.126 seconds, Fetched: 7 row(s)
通過上面的輸出,我們可以看到從wyp表中查詢出來的東西已經成功插入到test表中去了!如果目標表(test)中不存在分區字段,可以去掉partition (age=’25′)語句。當然,也可以在select語句里面通過使用分區值來動態指明分區:
hive> set hive.exec.dynamic.partition.mode=nonstrict;
hive> insert into table test
??? > partition (age)
??? > select id, name,
??? > tel, age
??? > from wyp;
#################################################################
?????????? 這里輸出了一堆Mapreduce任務信息,這里省略
#################################################################
Total MapReduce CPU Time Spent: 1 seconds 510 msec
OK
Time taken: 17.712 seconds
hive> select * from test;
OK
5?????? wyp1??? 131212121212??? 23
6?????? wyp2??? 134535353535??? 24
7?????? wyp3??? 132453535353??? 25
1?????? wyp???? 13188888888888? 25
8?????? wyp4??? 154243434355??? 26
2?????? test??? 13888888888888? 30
3?????? zs????? 899314121?????? 34
Time taken: 0.399 seconds, Fetched: 7 row(s)
這種方法叫做動態分區插入,但是Hive中默認是關閉的,所以在使用前需要先把hive.exec.dynamic.partition.mode設置為nonstrict。當然,Hive也支持insert overwrite方式來插入數據,從字面可以看出,overwrite是覆蓋的意思,執行完這條語句的時候,相應數據目錄下的數據將會被覆蓋,而insert into則不會。例子如下:
hive> insert overwrite table test
??? > PARTITION (age)
??? > select id, name, tel, age
??? > from wyp;
Hive還支持多表插入,在Hive中,可以把insert語句倒過來,把from放在最前面,它的執行效果和放在后面是一樣的,如下:
hive> show create table test3;
OK
CREATE? TABLE test3(
? id int,
? name string)
Time taken: 0.277 seconds, Fetched: 18 row(s)
hive> from wyp
??? > insert into table test
??? > partition(age)
??? > select id, name, tel, age
??? > insert into table test3
??? > select id, name
??? > where age>25;
?
hive> select * from test3;
OK
8?????? wyp4
2?????? test
3?????? zs
Time taken: 4.308 seconds, Fetched: 3 row(s)
可以在同一個查詢中使用多個insert子句,這樣只需要掃描一遍源表就可以生成多個不相交的輸出。
6.1.4??????????? 創建表時導入
在實際情況中,表的輸出結果可能太多,不適于顯示在控制臺上,這時候,將Hive的查詢輸出結果直接存在一個新的表中是非常方便的,稱這種情況為CTAS(create table as select)如下:
hive> create table test4
??? > as
??? > select id, name, tel
??? > from wyp;
hive> select * from test4;
OK
5?????? wyp1??? 131212121212
6?????? wyp2??? 134535353535
7?????? wyp3??? 132453535353
8?????? wyp4??? 154243434355
1?????? wyp???? 13188888888888
2?????? test??? 13888888888888
3?????? zs????? 899314121
Time taken: 0.089 seconds, Fetched: 7 row(s)
數據就插入到test4表中去了,CTAS操作是原子的,因此如果select查詢由于某種原因而失敗,新表是不會創建的。
6.2? Hive數據導出的方式
Hive根據導出的地方不同可以將導出方式分為三種:(1)導出到本地文件系統;(2)導出到HDFS中;(3)導出到Hive的另一個表中,下面逐一介紹。
6.2.1??????????? 導出到本地文件系統
hive> insert overwrite local directory '/home/wyp/wyp'
??? > select * from wyp;
這條HQL的執行需要啟用Mapreduce完成,運行完這條語句之后,將會在本地文件系統的/home/wyp/wyp目錄下生成文件,這個文件是Reduce產生的結果(這里生成的文件名是000000_0),我們可以看看這個文件的內容:
[wyp@master ~/wyp]$ vim 000000_0
5^Awyp1^A23^A131212121212
6^Awyp2^A24^A134535353535
7^Awyp3^A25^A132453535353
8^Awyp4^A26^A154243434355
1^Awyp^A25^A13188888888888
2^Atest^A30^A13888888888888
3^Azs^A34^A899314121
可以看出,這是wyp表中的所有數據。數據中的列與列之間的分隔符是^A(ascii碼是\00001)。
在Hive 0.11.0版本之前,數據的導出是不能指定列之間的分隔符的,只能用默認的列分隔符,也就是上面的^A來分割,這樣導出來的數據很不直觀,看起來很不方便。
如果用的Hive版本是0.11.0和之后版本,可以在導出數據的時候來指定列之間的分隔符,操作如下:
hive> insert overwrite local directory '/home/yangping.wu/local'
??? > row format delimited
??? > fields terminated by '\t'
??? > select * from wyp;
?
?[wyp@master ~/local]$ vim 000000_0
5?????? wyp1??? 23????? 131212121212
6?????? wyp2??? 24????? 134535353535
7?????? wyp3??? 25????? 132453535353
8?????? wyp4??? 26????? 154243434355
1?????? wyp???? 25????? 13188888888888
2?????? test??? 30????? 13888888888888
3?????? zs????? 34????? 899314121
其實,還可以用hive的-e和-f參數來導出數據。其中-e表示后面直接接帶雙引號的sql語句;而-f是接一個文件,文件的內容為一個sql語句,如下:
[wyp@master ~/local]$? hive -e "select * from wyp" >> local/wyp.txt
[wyp@master ~/local]$cat wyp.txt
5?????? wyp1??? 23????? 131212121212
6?????? wyp2??? 24????? 134535353535
7?????? wyp3??? 25????? 132453535353
8?????? wyp4??? 26????? 154243434355
1?????? wyp???? 25????? 13188888888888
2?????? test??? 30????? 13888888888888
3?????? zs????? 34????? 899314121
得到的結果也是用\t分割的。也可以用-f參數實現:
[wyp@master ~/local]$ cat wyp.sql
select * from wyp
[wyp@master ~/local]$ hive -f wyp.sql >> local/wyp2.txt
上述語句得到的結果也是\t分割的。
6.2.2??????????? 導出到HDFS中
和導入數據到本地文件系統一樣的簡單,可以用下面的語句實現:
hive> insert overwrite directory '/home/wyp/hdfs'
??? > select * from wyp;
將會在HDFS的/home/wyp/hdfs目錄下保存導出來的數據。注意,和導出文件到本地文件系統的HQL少一個local,數據的存放路徑就不一樣了。
6.2.3??????????? 導出到Hive的另一個表中
hive> insert into table test
??? > partition (age='25')
??? > select id, name, tel
??? > from wyp;
#################################################################
?????????? 這里輸出了一堆Mapreduce任務信息,這里省略
#################################################################
Total MapReduce CPU Time Spent: 1 seconds 310 msec
OK
Time taken: 19.125 seconds
hive> select * from test;
OK
5?????? wyp1??? 131212121212??? 25
6?????? wyp2??? 134535353535??? 25
7?????? wyp3??? 132453535353??? 25
8?????? wyp4??? 154243434355??? 25
1?????? wyp???? 13188888888888? 25
2?????? test??? 13888888888888? 25
3?????? zs???? ?899314121?????? 25
Time taken: 0.126 seconds, Fetched: 7 row(s)
其實就是講hive中一個表的內容導入到另一個表中。
7 ? ? ? ??Hive索引
索引是標準的數據庫技術,hive 0.7版本之后支持索引。Hive提供有限的索引功能,這不像傳統的關系型數據庫那樣有“鍵(key)”的概念,用戶可以在某些列上創建索引來加速某些操作,給一個表創建的索引數據被保存在另外的表中。 Hive的索引功能現在還相對較晚,提供的選項還較少。但是,索引被設計為可使用內置的可插拔的java代碼來定制,用戶可以擴展這個功能來滿足自己的需求。用戶可以使用EXPLAIN語法來分析HiveQL語句是否可以使用索引來提升用戶查詢的性能。像RDBMS中的索引一樣,需要評估索引創建的是否合理,畢竟,索引需要更多的磁盤空間,并且創建維護索引也會有一定的代價。 用戶必須要權衡從索引得到的好處和代價。
下面介紹創建索引的方法:
1. 先創建表:
hive> create table a3( id int, name string)
> ROW FORMAT DELIMITED
> FIELDS TERMINATED BY '\t'
> STORED AS TEXTFILE;
2. 導入數據:
hive> load data local inpath 'apache-hive-0.13.1-bin/a21.txt'
??? > overwrite into table a3;??????????????????????????????
Copying data from file:/usr/local/apache-hive-0.13.1-bin/a21.txt
Copying file: file:/usr/local/apache-hive-0.13.1-bin/a21.txt
Loading data to table default.a3
rmr: DEPRECATED: Please use 'rm -r' instead.
Deleted hdfs://localhost:9000/user/hive/warehouse/a3
Table default.a3 stats: [numFiles=1, numRows=0, totalSize=169, rawDataSize=0]
OK
Time taken: 0.468 seconds
3. 創建索引之前測試
hive> select * from a3 where id=28;
Total jobs = 1
Launching Job 1 out of 1
Number of reduce tasks is set to 0 since there's no reduce operator
Starting Job = job_1414112118511_0001, Tracking URL = http://h77.hadoop.org:8088/proxy/application_1414112118511_0001/
Kill Command = /usr/local/hadoop-2.4.1/bin/hadoop job? -kill job_1414112118511_0001
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 0
2014-10-24 09:12:11,220 Stage-1 map = 0%,? reduce = 0%
2014-10-24 09:12:16,404 Stage-1 map = 100%,? reduce = 0%, Cumulative CPU 1.13 sec
MapReduce Total cumulative CPU time: 1 seconds 130 msec
Ended Job = job_1414112118511_0001
MapReduce Jobs Launched:
Job 0: Map: 1?? Cumulative CPU: 1.13 sec?? HDFS Read: 375 HDFS Write: 8 SUCCESS
Total MapReduce CPU Time Spent: 1 seconds 130 msec
OK
28????? fdah
Time taken: 14.007 seconds, Fetched: 1 row(s)
一共用了14.007s
4. 對user創建索引
hive> create index a3_index on table a3(id)
??? > as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'
??? > with deferred rebuild
??? > in table a3_index_table;
OK
Time taken: 0.292 seconds
hive> alter index a3_index on a3 rebuild
??? > ;
Total jobs = 1
Launching Job 1 out of 1
Number of reduce tasks not specified. Estimated from input data size: 1
In order to change the average load for a reducer (in bytes):
? set hive.exec.reducers.bytes.per.reducer=<number>
In order to limit the maximum number of reducers:
? set hive.exec.reducers.max=<number>
In order to set a constant number of reducers:
? set mapreduce.job.reduces=<number>
Starting Job = job_1414112118511_0002, Tracking URL = http://h77.hadoop.org:8088/proxy/application_1414112118511_0002/
Kill Command = /usr/local/hadoop-2.4.1/bin/hadoop job? -kill job_1414112118511_0002
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1
2014-10-24 09:13:52,094 Stage-1 map = 0%,? reduce = 0%
2014-10-24 09:13:57,265 Stage-1 map = 100%,? reduce = 0%, Cumulative CPU 0.75 sec
2014-10-24 09:14:03,479 Stage-1 map = 100%,? reduce = 100%, Cumulative CPU 1.81 sec
MapReduce Total cumulative CPU time: 1 seconds 810 msec
Ended Job = job_1414112118511_0002
Loading data to table default.a3_index_table
rmr: DEPRECATED: Please use 'rm -r' instead.
Deleted hdfs://localhost:9000/user/hive/warehouse/a3_index_table
Table default.a3_index_table stats: [numFiles=1, numRows=20, totalSize=1197, rawDataSize=1177]
MapReduce Jobs Launched:
Job 0: Map: 1? Reduce: 1?? Cumulative CPU: 1.81 sec?? HDFS Read: 375 HDFS Write: 1277 SUCCESS
Total MapReduce CPU Time Spent: 1 seconds 810 msec
OK
Time taken: 17.976 seconds
hive> select * from a3_index_table;
OK
1?????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [0]
2?????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [6]
3?????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [12]
6?????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [40]
8?????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [18]
12????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [46]
18????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [54]
21????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [22]
28????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [128]
78????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [119]
83????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [136]
98????? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [153]
123???? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [27]
129???? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [161]
234???? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [80,109]
812???? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [144]
891???? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [34]
1231??? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [70,88]
2134??? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [61]
7897??? hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt??? [98]
Time taken: 0.041 seconds, Fetched: 20 row(s)
這樣對user表創建了一個索引。
5、對創建索引后的user再進行測試
hive> select * from a3 where id=28;??????????????????????????????????
Total jobs = 1
Launching Job 1 out of 1
Number of reduce tasks is set to 0 since there's no reduce operator
Starting Job = job_1414112118511_0003, Tracking URL = http://h77.hadoop.org:8088/proxy/application_1414112118511_0003/
Kill Command = /usr/local/hadoop-2.4.1/bin/hadoop job? -kill job_1414112118511_0003
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 0
2014-10-24 09:15:40,439 Stage-1 map = 0%,? reduce = 0%
2014-10-24 09:15:46,617 Stage-1 map = 100%,? reduce = 0%, Cumulative CPU 1.21 sec
MapReduce Total cumulative CPU time: 1 seconds 210 msec
Ended Job = job_1414112118511_0003
MapReduce Jobs Launched:
Job 0: Map: 1?? Cumulative CPU: 1.21 sec?? HDFS Read: 375 HDFS Write: 8 SUCCESS
Total MapReduce CPU Time Spent: 1 seconds 210 msec
OK
28????? fdah
Time taken: 11.924 seconds, Fetched: 1 row(s)
時間用了11.924s比沒有創建索引的效果好些,數據量大的時候效果會更明顯。
8 ? ? ? ??JDBC連接Hive Server
可以通過CLI、Client、Web UI等Hive提供的用戶接口來和Hive通信,但這三種方式最常用的是CLI;Client是Hive的客戶端,用來連接至Hive Server。在啟動Client模式的時候,需要指出Hive Server所在節點,并且在該節點啟動Hive Server。WUI是通過瀏覽器訪問 Hive。下面介紹通過HiveServer來操作Hive。
Hive提供了JDBC驅動,使得我們可以用Java代碼來連接Hive并進行一些類關系型數據庫的SQL語句查詢等操作。同關系型數據庫一樣,也需要將Hive的服務打開;在Hive 0.11.0版本之前,只有HiveServer服務可用,得在程序操作Hive之前,在安裝Hive的服務器上打開HiveServer服務,如下所示:
#bin/hive --service hiveserver -p 10002
Starting Hive Thrift Server
上面代表你已經成功的在端口為10002(默認的端口是10000)啟動了hiveserver服務。這時候,你就可以通過Java代碼來連接hiveserver,代碼如下:
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.DriverManager;
?
public class Testmzl {
?
?????? private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";
?
?????? public static void main(String[] args) throws SQLException {
?????? ?????? try {
?????? ?????? ?????? Class.forName(driverName);
?????? ?????? } catch (ClassNotFoundException e) {
?????? ?????? ?????? e.printStackTrace();
?????? ?????? ?????? System.exit(1);
?????? ?????? }
?
?????? ?????? Connection con = DriverManager.getConnection(
?????? ?????? ?????? ?????? "jdbc:hive://192.168.1.77:10002/default", "", "");
?????? ?????? Statement stmt = con.createStatement();
?????? ?????? String tableName = "wyp";
?????? ?????? stmt.execute("drop table if exists " + tableName);
?????? ?????? stmt.execute("create table " + tableName + " (key int, value string)");
?????? ?????? System.out.println("Create table success!");
?????? ?????? // show tables
?????? ?????? String sql = "show tables";
?????? ?????? System.out.println("Running: " + sql);
?????? ?????? ResultSet res = stmt.executeQuery(sql);
?????? ?????? while (res.next()) {
?????? ?????? ?????? System.out.println(res.getString(1));
?????? ?????? }
?
?????? ?????? // describe table
?????? ?????? sql = "describe " + tableName;
?????? ?????? System.out.println("Running: " + sql);
?????? ?????? res = stmt.executeQuery(sql);
?????? ?????? while (res.next()) {
?????? ?????? ?????? System.out.println(res.getString(1) + "\t" + res.getString(2));
?????? ?????? }
?
?????? ?????? sql = "select * from " + tableName;
?????? ?????? res = stmt.executeQuery(sql);
?????? ?????? while (res.next()) {
?????? ?????? ?????? System.out.println(String.valueOf(res.getInt(1)) + "\t"
?????? ?????? ?????? ?????? ?????? + res.getString(2));
?????? ?????? }
?
?????? ?????? sql = "select count(1) from " + tableName;
?????? ?????? System.out.println("Running: " + sql);
?????? ?????? res = stmt.executeQuery(sql);
?????? ?????? while (res.next()) {
?????? ?????? ?????? System.out.println(res.getString(1));
?????? ?????? }
?????? }
}
編譯上面的代碼,之后就可以運行,結果如下:
Create table success!
Running: show tables 'wyphao'
wyphao
Running: describe wyphao
key???????????????????? int???????????????
value?????????????????? string????????????
Running: select count(1) from wyphao
0
上面用Java連接HiveServer,而HiveServer本身存在很多問題(比如:安全性、并發性等);針對這些問題,Hive0.11.0版本提供了一個全新的服務:HiveServer2,這個很好的解決HiveServer存在的安全性、并發性等問題。這個服務啟動程序在${HIVE_HOME}/bin/hiveserver2里面,可以通過下面的方式來啟動HiveServer2服務:
$HIVE_HOME/bin/hiveserver2
也可以通過下面的方式啟動HiveServer2:
$HIVE_HOME/bin/hive --service hiveserver2
兩種方式效果一樣。但是之前的java程序需要修改兩個地方,如下所示:
private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";
改為
private static String driverName = "org.apache.hive.jdbc.HiveDriver";
?
Connection con = DriverManager.getConnection("jdbc:hive://localhost:10002/default", "", "");
改為
Connection con = DriverManager.getConnection("jdbc:hive2://localhost:10000/default", "", "");
其他的不變就可以了。
?
9 ? ? ? ??常見問題
9.1? disabled stack guard
在安裝運行hadoop時會出現下面的錯誤:
Hadoop 2.2.0 - warning: You have loaded library /home/hadoop/2.2.0/lib/native/libhadoop.so.1.0.0 which might have disabled stack guard.
具體出錯內容如下:
Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Starting namenodes on [Java HotSpot(TM) 64-Bit Server VM warning: You have loaded library /home/hadoop/2.2.0/lib/native/libhadoop.so.1.0.0 which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.
localhost]
sed: -e expression #1, char 6: unknown option to `s'
HotSpot(TM): ssh: Could not resolve hostname HotSpot(TM): Name or service not known
64-Bit: ssh: Could not resolve hostname 64-Bit: Name or service not known
Java: ssh: Could not resolve hostname Java: Name or service not known
Server: ssh: Could not resolve hostname Server: Name or service not known
VM: ssh: Could not resolve hostname VM: Name or service not known
解決方法:
[root@h77 hadoop-2.4.1]#vim etc/hadoop/hadoop-env.sh
在HADOOP_PREFIX變量的定義后面,HADOOP_OPTS變量的定義前面添加下列變量:
export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_PREFIX}/lib/native
export HADOOP_OPTS="-Djava.library.path=$HADOOP_PREFIX/lib"
9.2? javax.jdo.option.ConnectionURL配置的問題
Hive安裝過程中出現 The reference to entity "createDatabaseIfNotExist" must end with the ';' delimiter.問題,具體如下所示:
[Fatal Error] hive-site.xml:132:95: The reference to entity "createDatabaseIfNotExist" must end with the ';' delimiter.
14/10/23 11:15:04 FATAL conf.Configuration: error parsing conf file:/usr/local/apache-hive-0.13.1-bin/conf/hive-site.xml
org.xml.sax.SAXParseException; systemId: file:/usr/local/apache-hive-0.13.1-bin/conf/hive-site.xml; lineNumber: 132; columnNumber: 95; The reference to entity "createDatabaseIfNotExist" must end with the ';' delimiter.
顯示如下圖所示:
因為hive-site.xml中的javax.jdo.option.ConnectionURL配置項引起的,如下所示:
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost:3306/hive_hdp?characterEncoding=UTF-8&createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
正確配置如下:
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost:3306/hive_hdp?characterEncoding=UTF-8&createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
這是因為xml文件中的編碼規則引起的。
在xml文件中有以下幾類字符要進行轉義替換如下表所示:
符號 | Xml表示 | 含義 |
< | <? | 小于號 |
> | >? | 大于號 |
& | & | 和 |
' | ' | 單引號 |
" | " | 雙引號 |
所以javax.jdo.option.ConnectionURL項中的&符號需要用&表示。
10???????? Hive優化
10.1? 簡單查詢不啟用Mapreduce job
如果你想查詢某個表的某一列,Hive默認是會啟用MapReduce Job來完成這個任務:
hive> SELECT id, money FROM m limit 10;
Total MapReduce jobs = 1
Launching Job 1 out of 1
Number of reduce tasks is set to 0 since there's no reduce operator
Cannot run job locally: Input Size (= 235105473) is larger than
hive.exec.mode.local.auto.inputbytes.max (= 134217728)
Starting Job = job_1384246387966_0229, Tracking URL =
?
http://l-datalogm1.data.cn1:9981/proxy/application_1384246387966_0229/
?
Kill Command = /home/q/hadoop-2.2.0/bin/hadoop job
-kill job_1384246387966_0229
hadoop job information for Stage-1: number of mappers: 1;
number of reducers: 0
2013-11-13 11:35:16,167 Stage-1 map = 0%,? reduce = 0%
2013-11-13 11:35:21,327 Stage-1 map = 100%,? reduce = 0%,
Cumulative CPU 1.26 sec
2013-11-13 11:35:22,377 Stage-1 map = 100%,? reduce = 0%,
Cumulative CPU 1.26 sec
MapReduce Total cumulative CPU time: 1 seconds 260 msec
Ended Job = job_1384246387966_0229
MapReduce Jobs Launched:
Job 0: Map: 1?? Cumulative CPU: 1.26 sec?
HDFS Read: 8388865 HDFS Write: 60 SUCCESS
Total MapReduce CPU Time Spent: 1 seconds 260 msec
OK
1?????? 122
1?????? 185
1?????? 231
1?????? 292
1?????? 316
1 ??????329
1?????? 355
1?????? 356
1?????? 362
1?????? 364
Time taken: 16.802 seconds, Fetched: 10 row(s)
啟用MapReduce Job會消耗系統開銷,對于這個問題,從Hive0.10.0版本開始,對于簡單的不需要聚合的類似SELECT <col> from <table> LIMIT n語句,不需要起MapReduce job,直接通過Fetch task獲取數據,可以通過下面幾種方法實現:
方法一:
hive> set hive.fetch.task.conversion=more;
hive> SELECT id, money FROM m limit 10;
OK
1?????? 122
1?????? 185
1?????? 231
1?????? 292
1?????? 316
1?????? 329
1?????? 355
1?????? 356
1?????? 362
1?????? 364
Time taken: 0.138 seconds, Fetched: 10 row(s)
上面set hive.fetch.task.conversion=more;開啟了Fetch任務,所以對于上述簡單的列查詢不再啟用MapReduce job。
方法二:
bin/hive --hiveconf hive.fetch.task.conversion=more
方法三:
上面的兩種方法都可以開啟了Fetch任務,但是都是臨時起作用的;如果你想一直啟用這個功能,可以在${HIVE_HOME}/conf/hive-site.xml里面加入以下配置:
<property>
<name>hive.fetch.task.conversion</name>
<value>more</value>
<description>Some select queries can be converted to single FETCH task
minimizing latency.Currently the query should be single
sourced not having any subquery and should not have
any aggregations or distincts (which incurrs RS),
lateral views and joins.
1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
2. more??? : SELECT, FILTER, LIMIT only (+TABLESAMPLE, virtual columns)
</description>
</property>
這樣就可以長期啟用Fetch任務了。
11???????? 參考博文
本文主要參考下面的博文:
http://www.iteblog.com/archives/category/hive
轉載于:https://my.oschina.net/u/1169607/blog/342316
總結
以上是生活随笔為你收集整理的apache hive 使用概述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android组件之BroadCast简
- 下一篇: 二叉树的六种遍历方法汇总(转)