Hive配置運行及表的操作

jopen 10年前發布 | 43K 次閱讀 Hive 數據挖掘

配置Hive

Hive的配置文件名為hive-site.xml,你可以在Hive安裝目錄下的conf目錄下找到這個文件。如果你發現該目錄下沒有這個文件,你可以通過復制hive-default.xml.template來生成該文件。

當然,你也可以在進入hive時指定參數來明確指明配置文件所在目錄。比如:

hive --config /home/user/hive-conf

你也可以在進入hive時,通過命令行指定特定的配置參數值,比如:

hive --config fs.defalut.name=localhost:9000

以上命令在進入hive時,設置文件系統為localhost。如果在配置文件中同樣包含對該屬性值的設置,則命令行的設置將覆蓋配置文件中的設置。

你也可以在進入hive后,通過set命令進行設置,比如:

set fs.default.name=localhost:9000;

如以上所述,有很多方式都可以設置配置屬性值。如果在多個地方對同一屬性值進行了設置,則其優先級由高到低依次為:

l  Hive set命令

l  命令行—config設置

l  Hive-site.xml

l  Hive-default.xml

l  Hadoop-site.xml(或core-site.xml等)

l  Hadoop-default.xml

注意:以上提到的hadoop-site.xml及haddop-default.xml文件為Hadoop的配置文件,默認在Hadoop安裝目錄下的etc/hadoop目錄下。Pig通過Haddop相關的環境變量來獲取這些配置文件中的關聯信息。

日志

Hive默認的日志文件為/tmp/{user}/hive.log。當你運行hive過程中碰到問題需要分析時,查看這個日志文件是一個非常好的辦法。Hive默認使用log4j來記錄日志。


 

Hive服務

前面提到的Shell只是Hive提供的服務之一。你可以在命令行通過--service選項指定運行某一服務。Hive提供的服務包括:

1)      Cli

命令行接口(command lineinterface),即Shell。通過以下命令進入shell:

hive --service cli

注意:cli為默認方式,即以上命令等同于不帶任何參數的hive命令。

2)      Hiveserver

通過提供Thrift接口服務來運行Hive服務,可供多種客戶端通過Thrift來于Hive進行通訊。Thrift服務我們后續來講。

3)      Hwi

Hive的Web接口。

要使用hwi,需要先安裝ant,并配置ant的環境變量,比如:

export ANT_LIB=/user/share/ant/lib

完成后,運行以下命令:

Hive –service hwi

然后通過localhost:9999/hwi訪問。

 

注意:

訪問hwi時,可能會碰到各種各樣的問題,比如Unable to find a javac compiler等等。此時,請嘗試以下操作:

l  找到jdk目錄下的tools.jar,復制并拷貝到hive的lib目錄下。

l  找到ant目錄下的ant.jar和ant-launcher.jar文件,復制并拷貝到hive的lib目錄下。

4)      jar

與Hadoop Jar的使用方法類似。

5)      metadata

默認情況下,metadata和hive運行在同一進程中。通過此方式,可以讓metadata以單獨的進程運行。

6)      Hive客戶端

有很多種方式可以通過客戶端連接到Hive服務器。

l  Thrift 客戶端

l  JDBC驅動

l  ODBC驅動

我們在以后的實例中,逐個講解。

Metastore

Metastore包含兩個部分:服務和數據存儲。默認情況下,metastore服務和hive服務運行在同一個jvm中,包含一個內嵌的本地Derby數據庫實例。

使用內嵌的數據庫存儲metastore元數據是最簡單的處理方式。然而這就意味著同一時間只有一個Derby數據庫實例可以訪問數據庫磁盤文件,此時如果你啟動第二個回話,Hive就會報錯。

如果希望Hive支持多會話,我們就需要一個獨立的數據庫支持。這種方式我們稱之為本地Metastore(Local metastore)。在這種工作方式下,Metastore服務仍然和Hiveservice工作在同一個進程中,但是連接到一個獨立的數據庫服務進程(甚至可以是一個遠程的數據庫服務進程)。一般情況下支持JDBC的數據庫都可以配置作為該數據庫服務支持程序。

MySQL是一個非常合適的選擇,用來支持Metastore數據存儲。此種情況下,我們需要設置:

javax.jdo.option.ConnectionURL = jdbc:mysql://host/dbname?createDatabaseIfNotExist=true

javax.jdo.option.ConnectionDriverName = com.mysql.jdbc.Driver

javax.jdo.option.ConnectionUserName = username

javax.jdo.option.ConnectionPassword = password

注意:請確保對應的JDBC驅動的jar文件存在于hive的classpath,比如hive的lib目錄下。

另外一種方式我們稱之為遠程metastore。在這種配置下,Metastore服務運行在自己獨立的進程中,其他進程通過Thrift和metastore服務進行通訊。這種方式的好處之一就是客戶端不需要提供JDBC登錄信息等敏感數據。

注意:

Local或者Remote方式不是以數據庫是否在本地來區分的,也就是說remote方式下database數據庫仍然可以和Hive運行在同一個機器上。

請參照Hive官方文檔了解更多關于以上三種方式的詳細信息。

和傳統數據庫的比較

Hive某些方面和傳統數據庫是基本一致的,比如SQL語法。然而Hive的基于Mapreduce和hdfs的特性,決定了它和傳統數據庫是有很多顯著區別的。

讀時模式和寫時模式

傳統數據庫的表模式是有嚴格定義的,而且在數據加載時會驗證數據是否符合模式的要求,如果不符合則會拒絕載入數據。比如將一個字母插入到數值字段時,數據庫服務器會報錯從而導致操作失敗。我們稱此模式為“寫時模式”。

Hive則采用了不同的模式。它對數據的驗證不是發生在數據載入階段,而是發生在數據讀取階段。這就意味著,載入一個不符合模式的數據文件不會發生錯誤,但是一旦你執行譬如select語句時,則會發生錯誤。我們稱這種方式為“讀時模式”。

以上兩種方式的優點和缺點都很明顯。比如讀時模式在數據載入時非常快。而寫時模式則可以對字段進行索引,從而顯著提高查詢效率。

更新,事務和索引

更新,事務和索引是傳統數據的重要特性,但是Hive目前還不支持這幾種特性。

后續的Hive版本中會充分考慮這些特性。Hbase和Hive的集成正是了解這些特性的很好的例子。我們在Hbase中再做詳細介紹。

HiveQL

Hive所使用的SQL語言我們稱之為HiveQL,但是它并不完全支持SQL-92規范,畢竟Hive和傳統的數據庫系統是有不同應用場景的。再者,如果你發現SQL-92支持的某項功能HiveQL不支持,你也可以基于現有的HiveQL采用一些變通的方式來達成。

數據類型

Hive提供了基本數據類型和一些復雜數據類型。

基本數據類型包括:TINYINT,SMALLINT, INT, BIGINT, FLOAT, DOUBLE, BOOLEAN, STRING, BINARY, TIMESTAP。

復雜數據類型包括:ARRAY,MAP,STRUCT。

以上數據類型大部分通過字面意思即可知曉,我們不做詳述,稍后的實例中我們展開其用法。

數據類型轉換

和其它編程語言類似,Hive會在需要時執行一些自動轉換操作。比如一個表達式期望一個int,而實際提供的值是tinyint,則hive會自動將tinyint轉換為int。但是反過來,將int轉化為tinyint這種隱式轉換hive是不會發生的。除非你進行顯式轉換,比如CAST('1' AS INT)。

復雜數據類型

Hive提供了三種復雜數據類型:array,map, struct。

比如以下語句:

CREATE TABLE complex (

col1 ARRAY<INT>,

col2 MAP<STRING, INT>,

col3 STRUCT<a:STRING, b:INT, c:DOUBLE>

);

//TODO

操作與函數

Hive提供了常用的SQL操作,比如等值判斷x=’a’,空值判斷x isnull,模式匹配 x like ‘a%’等。

Hive提供了豐富的內置函數。你可以通過showfunctions來獲取函數列表。

當然,你也可以自己編寫自定義函數。稍后講解。

和傳統數據庫表的概念類似,hive表由表數據和描述表結構等的元數據組成。表數據一般存儲在HDFS中,當然也可以存在在其他文件系統,比如S3中;表的元數據存儲在一個關系型數據庫系統中,比如MySQL,而不是存儲在hdfs中。

注意:

傳統的關系數據庫支持多數據庫,比如它們都提供了create database語句。Hive早期版本不提供此功能,即所有表都存放在default數據庫中。而最近幾個版本的hive已經支持多數據庫,即你也可以在hive中使用create database語句創建數據庫,使用use語句卻換當前數據庫。

托管表和外部表(Managed table,External table)

默認情況下,當你創建Hive表時,hive將復雜管理表數據,即Hive會把表數據存儲到它的數據倉庫目錄下(warehouse directory)。這種方式創建的表我們稱之為托管表(managed table)。

另一種方式是創建一個外部表(External table)。此時,我們只需要告訴hive數據的外部引用地址,Hive本身不會在自己的數據倉庫目錄下存儲這些數據。

以下命令創建一個托管表并加載數據:

create table student(classNostring, stuNo string, score int) row format delimited fields terminated by ',';

load data local inpath '/home/user/input/student.txt'overwrite into table student;

執行以上命令時,hive將本地文件系統中的student.txt數據文件復制到hive的數據倉庫目錄下。此例中,數據文件地址為hdfs://localhost:9000/user/hive/warehouse/student/student.txt

此時,如果你執行以下語句:

DROP TABLE student;

Student表將會被刪除,包括表數據,元數據(metadata)。

 

注意:

關于元數據的存儲,默認情況下Hive使用內嵌的Derby數據庫來存儲。

在配置文件中你可以看到:

<property>

 <name>javax.jdo.option.ConnectionURL</name>

  <value>jdbc:derby:;databaseName=metastore_db;create=true</value>

  <description>JDBC connect string for aJDBC metastore</description>

</property>

注意紅色部分。元數據是存放在當前目錄下的,這就意味著以下場景會發生:

第一步:當前工作目錄為/root/A。進入hive shell后,hive會在/root/A目錄下創建元數據。

第二步:創建表student。

第三步:退出hive。

第四步:更改當前工作目錄為/root/B,再次進入hiveshell。

第五步:使用命令show tables。你會發現先前創建的student表并不存在。原因就是配置文件中,hive的元數據是存儲在當前目錄的metastore_db數據庫中的。這一步hive又會在/root/B目錄下創建一個新的metastore_db數據庫。

如果你希望將metastore存儲在固定位置,則你需要更改配置如下,此時無論你當前工作目錄是什么,hive都會讀取這個固定目錄下的metastore數據庫:

<property>

 <name>javax.jdo.option.ConnectionURL</name>

  <value>jdbc:derby:;databaseName=/opt/hive-0.11.0/metastore_db;create=true</value>

  <description>JDBC connect string for aJDBC metastore</description>

</property>

 

以下命令創建一個外部表:

Create external tableteacher(classNo string, teacherName string) row format delimited fields terminatedby ',' location '/user/hive/external/teacher';

注意:

location后面跟的是目錄名,而不是文件名。Hive會將整個目錄下的文件加載。目錄為hdfs下的目錄而不是本地文件系統的目錄。(因為此例中hive是工作在hdfs文件系統上的)

執行以下語句:

LOAD DATA INPATH '/user/hive/external/teacher_02.txt' INTO TABLE teacher;

注意:

此語句將會把/user/hive/external/teacher_02.txt'文件移動到/user/hive /external/teacher/目錄下;如果源數據在本地文件系統,則需要在INPATH前加上LOCAL選項,此時Hive會將源數據復制到表目錄下。

 

執行以下語句刪除外部表:

Drop table teacher;

以上語句只會刪除表的元數據(metastore),不會刪除表數據文件本身(本例中為teacher.txt和teacher_02.txt)。

分區和桶(Partitions,Buckets)

Hive通過分區(partitions)來組織表。這是一種通過分區列(partition column,比如日期)來對表進行劃分的粗粒度管理方式。

表或分區可以進一步劃分為桶(buckets)。桶為表數據提供了額外的結構信息,以提高查詢的效率。比如按用戶Id進行桶的劃分,能顯著提高基于用戶ID的查詢效率。

分區

假設我們有大量的日志文件,每一個日志記錄包含一個時間戳。我們以日期來對它進行分區,這樣的話,同一天的日志記錄就會被存放在同一個分區里。這就使得我們在查詢某一天(或多天)的日志記錄時能夠獲得非常高的查詢效率,因為hive只需要掃描特定的分區文件。

表的分區可以基于多個維度。比如,在按日期進行日志記錄分區的同時,再進一步根據日志類型進行子分區(subpartition)。這樣,當我們需要查詢特定類型的日志記錄時,就能夠獲得更高效率的查詢。

 

運行以下命令

Create external table yarnlog (createdtime string,category string,message string) partitioned by (date string,type string) rowformat delimited fields terminated by '\t';

注意:

Partitioned by子句緊跟在createtable后面。

Hive為yarnlog表創建了5個字段,分別為createdtime,category,message,date,type。可以用describeyarnlog來查看。

 

運行以下語句加載數據:

load data local inpath'/home/user/input/log/20140111/info' into table yarnlog partition(date='2014-01-11',type='INFO');

load data local inpath '/home/user/input/log/20140111/warn'into table yarnlog partition(date='2014-01-11',type='warn');

load data local inpath'/home/user/input/log/20140112/warn' into table yarnlogpartition(date='2014-01-12',type='warn');

load data local inpath'/home/user/input/log/20140112/info' into table yarnlogpartition(date='2014-01-12',type='INFO');

注意:

以上語句中的紅色部分。加載數據時,必須明確指明partition的各個字段值。Hive不能從數據文件中獲得任何partition字段值,因為load操作只復制數據文件而不會讀取文件內容。

加載完成后,hdfs中的/user/hive/warehouse目錄下的子目錄結構如下:

Yarnlog/

---------date=2014-01-11/

-------------------------------type=INFO/

-------------------------------type=warn/

---------date=2014-01-12/

-------------------------------type=INFO/

-------------------------------type=warn/

執行語句show partitions yarnlog,輸出如下:

date=2014-01-11/type=INFO

date=2014-01-11/type=warn

date=2014-01-12/type=INFO

date=2014-01-12/type=warn

 

分區列(partition column)是表的正式列,你可以像使用其他列一樣使用它。比如運行以下語句:

select message from yarnlog where type='warn';

此語句執行時僅僅掃描特定的分區文件。

 

備注:

以上使用到的日志文件格式為(tab分隔,你可以自己造一些測試數據):

2014-01-1208:51:04,818         WARN       Startingcontainer_1389456842640_0006_01_000002

使用桶的原因有兩個:提高特定條件下的查詢效率;更高效的執行取樣操作。

假如有兩個表按照字段uiserId進行join操作。Hive需要根據左表的某一個特定的userId來查找右表中關聯的記錄。如果這兩個表都按照相同的方式進行了桶劃分,則此時Hive在做匹配操作時,針對左表每一個特定的userId,只需要掃描右表的一個桶數據就可以了。(這么講解可能不太恰當,因為實際操作是由Hadoop的map操作來完成的)

 

執行以下語句:

create table student_bucketed (classNostring, stuNo string, score int) clustered by (classNo) sorted by (classNo)into 4 buckets row format delimited fields terminated by ',';

set hive.enforce.bucketing =true;

insert overwrite tablestudent_bucketed select * from student;

以上語句中的sorted by子句是可選的,該子句申明桶為排序桶,可以進一步提高map端的連接效率。桶的劃分是根據列值的hash值對桶個數的求余而來。

set hive.enforce.bucketing =true語句的作用是告訴Hive,Reduce的個數是和桶的個數一致的。如果不設置此屬性值,則需要用戶指定mapred.reduce.tasks屬性值。

 

執行以下語句對表數據取樣,返回大概三分之一的桶數據:

hive> select * fromstudent_bucketed tablesample(bucket 1 out of 3 on classno);

存儲格式(storage fromate)

Hive存儲格式涉及到兩個方面:行格式(rowformat)和文件格式(file format)。

創建表的時候如果沒有明確指明格式,則hive采用的默認格式為:文本文件,每行一個數據行。

Hive默認的行內分隔符不是tab,而是Ctrl+A(對應的ascii碼為1)。

Hive默認的集合內分隔符是Ctrl+B,用于分隔array,map以及struct中的鍵值。

表中各行以換行符分隔。

Create table時不指定任何分隔符,則其等價于以下語句:

CREATE TABLE 表名 (表字段)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\001'

COLLECTION ITEMS TERMINATED BY '\002'

MAP KEYS TERMINATED BY '\003'

LINES TERMINATED BY '\

STORED AS TEXTFILE;

以上STORE AS TEXTFILE指明文件格式為文本文件。

二進制存儲格式請參照官方文檔。

導入數據

除了前面提到的load語句外,我們還可以從已有的其他hive表中加載數據到特定的表。如前面提到的語句:

insert overwrite tablestudent_bucketed select * from student;

這個語句將會查詢student表中的所有數據并插入到student_bucketed表中。當然你還可以添加partition選項,這就是所謂的動態分區插入功能(dynamic-partition insert),不過你需要通過set hive.exec.dynamic.partition= true來啟用該功能。

 

注意:

以上語句中的overwrite是必須的,這就意味著目標表(或分區)將會被覆蓋。Hive目前還不支持往已有表(分區)中添加新紀錄的功能。

Hive不支持insert into tablevalues() 這樣的語句。

多表插入

Hive支持以下寫法:

FROM 源表

INSERT OVERWRITE TABLE 目標表1

SELECT 字段1 where條件1

INSERT OVERWRITE TABLE 目標表2

SELECT 字段2 where條件2

Select創建新表

和傳統的關系數據庫類似,Hive支持以下寫法:

CREATE TABLE 新表名

AS

SELECT col1, col2

FROM 源表;

表的修改

ALTER TABLE 表名 RENAME TO新的表名;

ALTER TABLE 表名 ADD COLUMNS (列名列類型);

更新信息請參照官方文檔。

表的刪除

以下語句刪除表的元數據及表數據(外部表只刪除元數據):

Drop table 表名

如果你只是想清空表數據而保留表的定義,你可以直接通過hdfs刪除表目錄下的文件即可。

以下語句將創建一個新表,其結構和已有的表相同,但是表數據為空:

CREATE TABLE 新表 LIKE已有的表;

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!