Hive中数据的导入与导出

时间:2024-01-13 17:35:14

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