最近在做一個小任務,將一個CDH平台中Hive的部分數據同步到另一個平台中。畢竟我也剛開始工作,在正式開始做之前,首先進行了一段時間的練習,下面的內容就是練習時寫的文檔中的內容。如果哪里有錯誤或者疏漏,希望各位網友能夠指出。
第一篇:HDFS的上傳與下載(put & get):https://www.cnblogs.com/BlackString/p/10552553.html
第三篇:Hive分區表的導入與導出:https://www.cnblogs.com/BlackString/p/10552901.html
第四篇:跨平台傳輸方案:https://www.cnblogs.com/BlackString/p/10553010.html
Hive數據的上傳/導入
1. 前言
上一篇中,我們嘗試了向HDFS中上傳及下載文件的測試。在本篇,我們嘗試從Hive中導出/導入數據。
2. Hive中的數據
Hive中表數據對應着HDFS中的warehouse目錄中的文件。其中:
一個數據庫對應一個.db文件;
一個表對應.db文件中的一個文件夾;
表中的每個分區對應着表文件夾中的一個文件夾;
表中的每個桶對應着每個分區文件夾中的一個文件;
檢查Hive,發現Hive中有5個表:
shell
hive> show databases;
db_zh_dw
db_zh_dw2
default
test
test02
查看HDFS中的 /user/hive/warehouse 目錄,在其中發現了以下文件:
drwxrwxrwt - admin hive /user/hive/warehouse/db_zh_dw.db
drwxrwxrwt - admin hive /user/hive/warehouse/test.db
drwxrwxrwt - root hive /user/hive/warehouse/test02.db
我們以test數據庫為例,查看test中的表及test.db文件中的內容:
hive> show tables;
aos_dic
aos_role
aosparams
————————————————————————————————
[root@DataCenter2 ~]# hadoop fs -ls /user/hive/warehouse/test.db
drwxrwxrwt - hdfs hive /user/hive/warehouse/test.db/aos_dic
drwxrwxrwt - hdfs hive /user/hive/warehouse/test.db/aos_role
drwxrwxrwt - hdfs hive /user/hive/warehouse/test.db/aosparams
從上可見,每個數據表對應着test.db中的一個文件夾。以aos_dic.db表為例,讓我們查看其中的數據:
[root@DataCenter2 ~]# hadoop fs -ls /user/hive/warehouse/test.db/aos_dic;
-rwxrwxrwt 3 hdfs hive 1588 2018-09-21 14:13 /user/hive/warehouse/test.db/aos_dic/part-m-00000
-rwxrwxrwt 3 hdfs hive 663 2018-09-21 14:13 /user/hive/warehouse/test.db/aos_dic/part-m-00001
-rwxrwxrwt 3 hdfs hive 2019 2018-09-21 14:13 /user/hive/warehouse/test.db/aos_dic/part-m-00002
-rwxrwxrwt 3 hdfs hive 254 2018-09-21 14:13 /user/hive/warehouse/test.db/aos_dic/part-m-00003
可以看到該表中有四個文件(事實上,這四個表中就存儲了aos_dic表中的所有數據,即該表不是一個分區表)。讓我們查看該表的創建語句,其中有:
LOCATION 'hdfs://DataCenter3:8020/user/hive/warehouse/test.db/aos_dic'
這意味着該表是一個外部表。那么,假如我們向aos_dic中上傳新文件,aos_dic表中的數據行是否會增多?
3. 向Hive中上傳新文件
1)還是拿test庫下的aos_dic表為例。此時此表中的數據行有:
hive> select count(*) from aos_dic;
80
此時aos_dic表中有80行數據。
2)我們仿照aos_dic中的文件創建一個新文件:part-m-00004,並在其中寫入符合格式的10行數據,然后將該文件上傳到aos_dic文件夾下:
sudo -u hdfs hadoop fs -put part-m-00004 /user/hive/warehouse/test.db/aos_dic
3)上傳完畢,到hive中查看aos_dic表中的數據是否增多:
hive> select count(*) from aos_dic;
90
4)由上可見,我們上傳的數據也出現在了aos_dic表中。
4. hive export 和 hive import 的使用
Export命令可以導出一張表或分區的數據和元數據信息到一個輸出位置,並且導出數據可以被移動到另一個hadoop集群或hive實例,並且可以通過import命令導入數據。
當導出一個分區表,原始數據可能在hdfs的不同位置,export/import命令也支持導出分區表的不同子分區。
導出的元數據存儲在目標目錄,並且數據文件是存儲在不同的子目錄下。
Export/import命令可以獨立工作在使用存儲元數據的rdbms中。
語法
1)export語法:
EXPORT TABLE tablename [PARTITION (part_column="value"[, ...])]
TO 'export_target_path' [ FOR replication('eventid') ]
2)import語法:
IMPORT [[EXTERNAL] TABLE new_or_original_tablename [PARTITION (part_column="value"[, ...])]]
FROM 'source_path'
[LOCATION 'import_target_path']
練習
1)導出練習:
將test02庫中的tt03表(非分區表,外部表)導出到 /user/test 下(也可以不用新建文件夾,導出時會自動創建):
export table tt03 to '/user/test';
到 /user/test 下查看,會發現多出了兩個新文件。從下面的結果中可以看出,兩個文件中,一個保留了tt03表的元數據信息,一個存儲了tt03的外部數據文件:
[root@DataCenter2 tt02]# hadoop fs -ls /user/test
-rwxr-xr-x 3 root supergroup 1392 2019-03-15 14:30 /user/test/_metadata
drwxr-xr-x - root supergroup 0 2019-03-15 14:30 /user/test/data
[root@DataCenter2 tt02]# hadoop fs -ls /user/test/data
-rwxr-xr-x 3 root supergroup 132 2019-03-15 14:30 /user/test/data/part01.txt
-rwxr-xr-x 3 root supergroup 142 2019-03-15 14:30 /user/test/data/part02.txt
-rwxr-xr-x 3 root supergroup 141 2019-03-15 14:30 /user/test/data/part03.txt
————————————————————————————————————
[root@DataCenter2 tt02]# hadoop fs -cat /user/test/_metadata
元數據略;
2)導入練習:
將1)中導出的信息導入到test03庫中:
hive> import from '/user/test';
導入成功,會發現test03下多出了一個表tt03:
hive> show tables;
tt03
查看tt03中的數據,發現和test02庫中的tt03表一致。
而到tt03在HDFS中的文件查看,會發現test03庫下多出了一個文件夾tt03,而tt03中包含了原tt03的所有外部文件:
[root@DataCenter2 tt02]# hadoop fs -ls /user/hive/warehouse/test03.db/tt03
-rwxrwxrwt 3 root supergroup 132 2019-03-15 14:31 /user/hive/warehouse/test03.db/tt03/part01.txt
-rwxrwxrwt 3 root supergroup 142 2019-03-15 14:31 /user/hive/warehouse/test03.db/tt03/part02.txt
-rwxrwxrwt 3 root supergroup 141 2019-03-15 14:31 /user/hive/warehouse/test03.db/tt03/part03.txt
除了直接導入原表外,還可以在導入時重命名導入的表:
hive> import table tt02 from '/user/test';
3)關於內外部表,import后的不同:
一個內部表的信息,被導入后仍然是一個內部表,在hive中刪除該表,對應的庫中的文件也會被刪除;
一個外部表的信息,被導入后仍然是一個外部表,在hive中刪除該表,對應庫中的文件不會被刪除;
但是,一個內部表的信息在導入時可以被導入為一個外部表:
hive> import external table tt01 from '/user/test/test01';
到該表所在的數據庫中查看,會發現.db文件下多出了一個文件夾tt01,但是其中沒有任何數據,此時刪除該表這個文件夾也不會消失。
向導入的表tt01中插入數據,插入成功后去查看.db下出現的tt01文件夾,會發現它仍然是一個空文件夾,到導入數據所在的文件夾下,會發現多出了一條新數據——正是我們剛剛插入的那條數據。
4)指定導入位置:
在導入一個表時,我們可以指定這個表導入的位置,如:
hive> import from '/user/test/test01' location '/user/test/test02';
查看該表,發現其中包含了所有的數據。如果此時去test03.db下查看,會發現並不存在名為tt01的文件夾。在這條指令中,我們在 /user/test 下新建了一個test02文件夾,並在導入時定位到了這里。此時,我們到該文件夾下
查看,會發現其中包含了tt01的所有數據。
向tt01中插入一條新數據,.db下並沒有出現新文件,到test02文件夾下查看,會發現新增了一個文件,其中記錄了新插入的數據。
刪除test02文件夾,會發現test03庫中tt01仍然存在,但是卻不含任何數據。向其中插入一條新數據,會發現 /user/test 下重新出現了test02文件夾,其中包含了剛剛插入的那條數據。
5)導入/導出分區:
那么,對於分區表要如何導出/導入呢?
使用以下語句導出一個分區表的某個分區:
hive> export table tt02 partition(birth='1997') to '/user/test/test03';
使用以下語句導入一個分區表:
hive> import table tt02 partition(birth='1997') from '/user/test/test03';
會發現已經導入了一個分區表,這個分區表中包含了一個分區。當然我們也可以導入更多的分區:
hive> import table tt02 partition(birth='1999') from '/user/test/test04';
成功后會發現該表又多處一個新的分區。到.db文件下,會發現tt02文件夾中包含了導入的兩個分區:
[root@DataCenter2 Test]# hadoop fs -ls /user/hive/warehouse/test03.db/tt02
drwxrwxrwt - root hive 0 2019-03-15 15:39 /user/hive/warehouse/test03.db/tt02/birth=1997
drwxrwxrwt - root hive 0 2019-03-15 15:50 /user/hive/warehouse/test03.db/tt02/birth=1999
分區表可以進行拓展,但是普通的表卻無法進行拓展,一旦表中已經存在數據就無法再導入數據(空表則可以,但是字段要對應)。
此外,能否一次性導出多個分區?我一開始認為有可能,但是經過數個小時的測試和查詢,我不得不認為,應該是無法一次導出多個分區的。
【3月28日更新:這個結論是我一開始得出的,但是今天我得知了動態分區的存在,根據動態分區的設定,一次性導入多個分區的數據是可以用動態分區實現的】