Hive的幾種常見的數據導入方式
這里介紹四種:
(1)、從本地文件系統中導入數據到Hive表;
(2)、從HDFS上導入數據到Hive表;
(3)、從別的表中查詢出相應的數據並導入到Hive表中;
(4)、在創建表的時候通過從別的表中查詢出相應的記錄並插入到所創建的表中。
一、從本地文件系統中導入數據到Hive表
先在Hive里面創建好表,如下:
1. hive> create table wyp
2. > (id int, name string,
3. > age int, tel string)
4. > ROW FORMAT DELIMITED
5. > FIELDS TERMINATED BY '\t'
6. > STORED AS TEXTFILE;
7. OK
8. Time taken: 2.832 seconds
這個表很簡單,只有四個字段,具體含義我就不解釋了。本地文件系統里面有個/home/wyp/wyp.txt文件,內容如下:
1. [wyp@master ~]$ cat wyp.txt
2. 1 wyp 25 13188888888888
3. 2 test 30 13888888888888
4. 3 zs 34 899314121
wyp.txt文件中的數據列之間是使用\t分割的,可以通過下面的語句將這個文件里面的數據導入到wyp表里面,操作如下:
1. hive> load data local inpath 'wyp.txt' into table wyp;
2. Copying data from file:/home/wyp/wyp.txt
3. Copying file: file:/home/wyp/wyp.txt
4. Loading data to table default.wyp
5. Table default.wyp stats:
6. [num_partitions: 0, num_files: 1, num_rows: 0,total_size: 67]
7. OK
8. Time taken: 5.967 seconds
這樣就將wyp.txt里面的內容導入到wyp表里面去了,可以到wyp表的數據目錄下查看,如下命令:
1. hive> dfs -ls /user/hive/warehouse/wyp ;
2. Found 1 items
3. -rw-r--r--3 wyp supergroup 67 2014-02-19 18:23/hive/warehouse/wyp/wyp.txt
需要注意的是:
和我們熟悉的關系型數據庫不一樣,Hive現在還不支持在insert語句里面直接給出一組記錄的文字形式,也就是說,Hive並不支持INSERT INTO …. VALUES形式的語句。
二、HDFS上導入數據到Hive表
從本地文件系統中將數據導入到Hive表的過程中,其實是先將數據臨時復制到HDFS的一個目錄下(典型的情況是復制到上傳用戶的HDFS home目錄下,比如/home/wyp/),然后再將數據從那個臨時目錄下移動(注意,這里說的是移動,不是復制!)到對應的Hive表的數據目錄里面。既然如此,那么Hive肯定支持將數據直接從HDFS上的一個目錄移動到相應Hive表的數據目錄下,假設有下面這個文件/home/wyp/add.txt,具體的操作如下:
1. [wyp@master /home/q/hadoop-2.2.0]$bin/hadoop fs -cat /home/wyp/add.txt
2. 5 wyp1 23 131212121212
3. 6 wyp2 24 134535353535
4. 7 wyp3 25 132453535353
5. 8 wyp4 26 154243434355
上面是需要插入數據的內容,這個文件是存放在HDFS上/home/wyp目錄(和一中提到的不同,一中提到的文件是存放在本地文件系統上)里面,我們可以通過下面的命令將這個文件里面的內容導入到Hive表中,具體操作如下:
1. hive> load data inpath '/home/wyp/add.txt' into tablewyp;
2. Loading data to table default.wyp
3. Table default.wyp stats:
4. [num_partitions: 0, num_files: 2, num_rows: 0,total_size: 215]
5. OK
6. Time taken: 0.47 seconds
7.
8. hive> select * from wyp;
9. OK
10.5 wyp1 23 131212121212
11.6 wyp2 24 134535353535
12.7 wyp3 25 132453535353
13.8 wyp4 26 154243434355
14.1 wyp 25 13188888888888
15.2 test 30 13888888888888
16.3 zs 34 899314121
17.Time taken: 0.096 seconds, Fetched: 7 row(s)
從上面的執行結果我們可以看到,數據的確導入到wyp表中了!請注意load data inpath ‘/home/wyp/add.txt’ intotable wyp;里面是沒有local這個單詞的,這個是和一中的區別。
三、從別的表中查詢出相應的數據並導入到Hive表中
假設Hive中有test表,其建表語句如下所示:
1. hive> create table test(
2. > id int, name string
3. > ,tel string)
4. > partitioned by
5. > (age int)
6. > ROW FORMAT DELIMITED
7. > FIELDS TERMINATED BY '\t'
8. > STORED AS TEXTFILE;
9. OK
10.Time taken: 0.261 second
大體和wyp表的建表語句類似,只不過test表里面用age作為了分區字段。對於分區,這里在做解釋一下:
分區:在Hive中,表的每一個分區對應表下的相應目錄,所有分區的數據都是存儲在對應的目錄中。比如wyp表有dt和city兩個分區,則對應dt=20131218,city=BJ對應表的目錄為/user/hive/warehouse/dt=20131218/city=BJ,所有屬於這個分區的數據都存放在這個目錄中。
下面語句就是將wyp表中的查詢結果並插入到test表中:
1. hive> insert into table test
2. > partition (age='25')
3. > select id, name, tel
4. > from wyp;
5. #####################################################################
6. 這里輸出了一堆Mapreduce任務信息,這里省略
7. #####################################################################
8. Total MapReduce CPU Time Spent: 1 seconds 310 msec
9. OK
10.Time taken: 19.125 seconds
11.
12.hive> select * from test;
13.OK
14.5 wyp1 131212121212 25
15.6 wyp2 134535353535 25
16.7 wyp3 132453535353 25
17.8 wyp4 154243434355 25
18.1 wyp 13188888888888 25
19.2 test 13888888888888 25
20.3 zs 899314121 25
21.Time taken: 0.126 seconds, Fetched: 7 row(s)
這里做一下說明:
我們知道我們傳統數據塊的形式insertinto table values(字段1,字段2),這種形式hive是不支持的。
通過上面的輸出,我們可以看到從wyp表中查詢出來的東西已經成功插入到test表中去了!如果目標表(test)中不存在分區字段,可以去掉partition(age=’25′)語句。當然,我們也可以在select語句里面通過使用分區值來動態指明分區:
1. hive> set hive.exec.dynamic.partition.mode=nonstrict;
2. hive> insert into table test
3. > partition (age)
4. > select id, name,
5. > tel, age
6. > from wyp;
7. #####################################################################
8. 這里輸出了一堆Mapreduce任務信息,這里省略
9. #####################################################################
10.Total MapReduce CPU Time Spent: 1 seconds 510 msec
11.OK
12.Time taken: 17.712 seconds
13.
14.
15.hive> select * from test;
16.OK
17.5 wyp1 131212121212 23
18.6 wyp2 134535353535 24
19.7 wyp3 132453535353 25
20.1 wyp 13188888888888 25
21.8 wyp4 154243434355 26
22.2 test 13888888888888 30
23.3 zs 899314121 34
24.Time taken: 0.399 seconds, Fetched: 7 row(s)
這種方法叫做動態分區插入,但是Hive中默認是關閉的,所以在使用前需要先把hive.exec.dynamic.partition.mode設置為nonstrict。當然,Hive也支持insertoverwrite方式來插入數據,從字面我們就可以看出,overwrite是覆蓋的意思,是的,執行完這條語句的時候,相應數據目錄下的數據將會被覆蓋!而insert into則不會,注意兩者之間的區別。例子如下:
1. hive> insert overwrite table test
2. > PARTITION (age)
3. > select id, name, tel, age
4. > from wyp;
更可喜的是,Hive還支持多表插入,什么意思呢?在Hive中,我們可以把insert語句倒過來,把from放在最前面,它的執行效果和放在后面是一樣的,如下:
1. hive> show create table test3;
2. OK
3. CREATE TABLE test3(
4. id int,
5. name string)
6. Time taken: 0.277 seconds, Fetched: 18 row(s)
7.
8. hive> from wyp
9. > insert into table test
10. > partition(age)
11. > select id, name, tel, age
12. > insert into table test3
13. > select id, name
14. > where age>25;
15.
16.hive> select * from test3;
17.OK
18.8 wyp4
19.2 test
20.3 zs
21.Time taken: 4.308 seconds, Fetched: 3 row(s)
可以在同一個查詢中使用多個insert子句,這樣的好處是我們只需要掃描一遍源表就可以生成多個不相交的輸出。這個很酷吧!
四、在創建表的時候通過從別的表中查詢出相應的記錄並插入到所創建的表中
在實際情況中,表的輸出結果可能太多,不適於顯示在控制台上,這時候,將Hive的查詢輸出結果直接存在一個新的表中是非常方便的,我們稱這種情況為CTAS(create table .. as select)如下:
1. hive> create table test4
2. > as
3. > select id, name, tel
4. > from wyp;
5.
6. hive> select * from test4;
7. OK
8. 5 wyp1 131212121212
9. 6 wyp2 134535353535
10.7 wyp3 132453535353
11.8 wyp4 154243434355
12.1 wyp 13188888888888
13.2 test 13888888888888
14.3 zs 899314121
15.Time taken: 0.089 seconds, Fetched: 7 row(s)
數據就插入到test4表中去了,CTAS操作是原子的,因此如果select查詢由於某種原因而失敗,新表是不會創建的!