Hive的基本使用與匯入匯出資料
Hive的資料匯入匯出
-
從本地檔案系統中匯入資料到Hive表;
-
從HDFS上匯入資料到Hive表;
-
從別的表中查詢出相應的資料並匯入到Hive表中;
-
在建立表的時候通過從別的表中查詢出相應的記錄並插入到所建立的表中。
1、從本地檔案系統中匯入資料到Hive表先在Hive裡面建立好表
如下:
-
hive>create table wyp(idint,namestring,ageint,telstring)ROW FORMAT DELIMITED FIELDS TERMINATED BY'\t'STORED AS TEXTFILE;
這個表很簡單,只有四個欄位,具體含義我就不解釋了。本地檔案系統裡面有個/home/wyp/wyp.txt檔案,內容如下:
[[email protected]~]$ cat wyp.txt
1wyp2513188888888888
2test3013888888888888
3zs34899314121
wyp.txt檔案中的資料列之間是使用\t分割的,可以通過下面的語句將這個檔案裡面的資料匯入到wyp表裡面,操作如下:
-
hive>load datalocalinpath'wyp.txt'intotable wyp;
-
Copyingdatafromfile:/home/wyp/wyp.txt
-
Copyingfile:file:/home/wyp/wyp.txt
-
Loadingdata to tabledefault.wyp
-
Tabledefault.wyp stats:
-
[num_partitions:0,num_files:1,num_rows:0,total_size:67]
-
OK
-
Timetaken:5.967seconds
這樣就將wyp.txt裡面的內容匯入到wyp表裡面去了,可以到wyp表的資料目錄下檢視,如下命令:
-
hive>dfs-ls/user/hive/warehouse/wyp;
-
Found1items
-
-rw-r--r--3wyp supergroup672014-02-1918:23/hive/warehouse/wyp/wyp.txt
需要注意的是:
和我們熟悉的關係型資料庫不一樣,Hive現在還不支援在insert語句裡面直接給出一組記錄的文字形式,也就是說,Hive並不支援INSERT INTO …. VALUES形式的語句。
2、HDFS上匯入資料到Hive表
從本地檔案系統中將資料匯入到Hive表的過程中,其實是先將資料臨時複製到HDFS的一個目錄下(典型的情況是複製到上傳使用者的HDFS home目錄下,比如/home/wyp/),然後再將資料從那個臨時目錄下移動(注意,這裡說的是移動,不是複製!)到對應的Hive表的資料目錄裡面。
既然如此,那麼Hive肯定支援將資料直接從HDFS上的一個目錄移動到相應Hive表的資料目錄下,假設有下面這個檔案/home/wyp/add.txt,具體的操作如下:
-
[[email protected]/home/q/hadoop-2.2.0]$ bin/hadoop fs-cat/home/wyp/add.txt
-
5wyp123131212121212
-
6wyp224134535353535
-
7wyp325132453535353
-
8wyp426154243434355
上面是需要插入資料的內容,這個檔案是存放在HDFS上/home/wyp目錄(和一中提到的不同,一中提到的檔案是存放在本地檔案系統上)裡面,我們可以通過下面的命令將這個檔案裡面的內容匯入到Hive表中,具體操作如下:
-
hive>load data inpath'/home/wyp/add.txt'intotable wyp;
-
Loadingdata to tabledefault.wyp
-
Tabledefault.wyp stats:
-
[num_partitions:0,num_files:2,num_rows:0,total_size:215]
-
OK
-
Timetaken:0.47seconds
-
hive>select*fromwyp;
-
OK
-
5wyp123131212121212
-
6wyp224134535353535
-
7wyp325132453535353
-
8wyp426154243434355
-
1wyp2513188888888888
-
2test3013888888888888
-
3zs34899314121
-
Timetaken:0.096seconds,Fetched:7row(s)
從上面的執行結果我們可以看到,資料的確匯入到wyp表中了!請注意load data inpath ‘/home/wyp/add.txt’ into table wyp;裡面是沒有local這個單詞的,這個是和一中的區別。
3、從別的表中查詢出相應的資料並匯入到Hive表中
假設Hive中有test表,其建表語句如下所示:
-
hive>create table test(
-
>idint,namestring
-
>,telstring)
-
>partitionedby
-
>(ageint)
-
>ROW FORMAT DELIMITED
-
>FIELDS TERMINATED BY'\t'
-
>STORED AS TEXTFILE;
-
OK
-
Timetaken:0.261seconds
-
下面語句就是將wyp表中的查詢結果並插入到test表中:
-
hive>insertintotable test
-
>partition(age='25')
-
>selectid,name,tel
-
>fromwyp;
-
#####################################################################
-
這裡輸出了一堆Mapreduce任務資訊,這裡省略
-
#####################################################################
-
TotalMapReduceCPUTimeSpent:1seconds310msec
-
OK
-
Timetaken:19.125seconds
-
hive>select*fromtest;
-
OK
-
5wyp113121212121225
-
6wyp213453535353525
-
7wyp313245353535325
-
8wyp415424343435525
-
1wyp1318888888888825
-
2test1388888888888825
-
3zs89931412125
-
Timetaken:0.126seconds,Fetched:7row(s)
這裡做一下說明:我們知道我們傳統資料塊的形式insert into table values(欄位1,欄位2),這種形式hive是不支援的。
通過上面的輸出,我們可以看到從wyp表中查詢出來的東西已經成功插入到test表中去了!如果目標表(test)中不存在分割槽欄位,可以去掉partition (age=’25′)語句。當然,我們也可以在select語句裡面通過使用分割槽值來動態指明分割槽:
-
hive>sethive.exec.dynamic.partition.mode=nonstrict;
-
hive>insertintotable test
-
>partition(age)
-
>selectid,name,
-
>tel,age
-
>fromwyp;
-
#####################################################################
-
這裡輸出了一堆Mapreduce任務資訊,這裡省略
-
#####################################################################
-
TotalMapReduceCPUTimeSpent:1seconds510msec
-
OK
-
Timetaken:17.712seconds
-
hive>select*fromtest;
-
OK
-
5wyp113121212121223
-
6wyp213453535353524
-
7wyp313245353535325
-
1wyp1318888888888825
-
8wyp415424343435526
-
2test1388888888888830
-
3zs89931412134
-
Timetaken:0.399seconds,Fetched:7row(s)
這種方法叫做動態分割槽插入,但是Hive中預設是關閉的,所以在使用前需要先把hive.exec.dynamic.partition.mode設定為nonstrict。當然,Hive也支援insert overwrite方式來插入資料,從字面我們就可以看出,overwrite是覆蓋的意思,是的,執行完這條語句的時候,相應資料目錄下的資料將會被覆蓋!而insert into則不會,注意兩者之間的區別。例子如下:
-
hive>insert overwrite table test
-
>PARTITION(age)
-
>selectid,name,tel,age
-
>fromwyp;
-
更可喜的是,Hive還支援多表插入,什麼意思呢?在Hive中,我們可以把insert語句倒過來,把from放在最前面,它的執行效果和放在後面是一樣的,如下:
-
hive>show create table test3;
-
OK
-
CREATE TABLE test3(
-
idint,
-
namestring)
-
Timetaken:0.277seconds,Fetched:18row(s)
-
hive>fromwyp
-
>insertintotable test
-
>partition(age)
-
>selectid,name,tel,age
-
>insertintotable test3
-
>selectid,name
-
>whereage>25;
-
hive>select*fromtest3;
-
OK
-
8wyp4
-
2test
-
3zs
-
Timetaken:4.308seconds,Fetched:3row(s)
可以在同一個查詢中使用多個insert子句,這樣的好處是我們只需要掃描一遍源表就可以生成多個不相交的輸出。這個很酷吧!
4、在建立表的時候通過從別的表中查詢出相應的記錄並插入到所建立的表中
在實際情況中,表的輸出結果可能太多,不適於顯示在控制檯上,這時候,將Hive的查詢輸出結果直接存在一個新的表中是非常方便的,我們稱這種情況為CTAS(create table .. as select)如下:
-
hive>create table test4
-
>as
-
>selectid,name,tel
-
>fromwyp;
-
hive>select*fromtest4;
-
OK
-
5wyp1131212121212
-
6wyp2134535353535
-
7wyp3132453535353
-
8wyp4154243434355
-
1wyp13188888888888
-
2test13888888888888
-
3zs899314121
-
Timetaken:0.089seconds,Fetched:7row(s)
資料就插入到test4表中去了,CTAS操作是原子的,因此如果select查詢由於某種原因而失敗,新表是不會建立的!
Hive資料的匯出
根據匯出的地方不一樣,將這些方式分為三種:
-
匯出到本地檔案系統;
-
匯出到HDFS中;
-
匯出到Hive的另一個表中。
1、匯出到本地檔案系統
-
hive>insert overwritelocaldirectory'/home/wyp/wyp'
-
>select*fromwyp;
-
這條HQL的執行需要啟用Mapreduce完成,執行完這條語句之後,將會在本地檔案系統的/home/wyp/wyp目錄下生成檔案,這個檔案是Reduce產生的結果(這裡生成的檔名是000000_0),我們可以看看這個檔案的內容:
-
[[email protected]~/wyp]$ vim000000_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不一樣,不能用insert into來將資料匯出:
-
###2、匯出到HDFS中
-
和匯入資料到本地檔案系統一樣的簡單,可以用下面的語句實現:
hive> insert overwrite directory ‘/home/wyp/hdfs’
select * from wyp;```將會在HDFS的/home/wyp/hdfs目錄下儲存匯出來的資料。注意,和匯出檔案到本地檔案系統的HQL少一個local,資料的存放路徑就不一樣了。