最近在做一个小任务,将一个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日更新:这个结论是我一开始得出的,但是今天我得知了动态分区的存在,根据动态分区的设定,一次性导入多个分区的数据是可以用动态分区实现的】