0


Hive外表创建和加载数据

Hive内表和外表的区别

外表:
需要external关键字,location是数据文件默认存放位置,不管是select还是load的数据都存放在这里。导入数据到外部表,数据并没有mv到数据仓库目录,而是在loacation目录。
内表:
内部表建表时也能加上location,作用和外部表一样,都是表数据的存放路径,不同的是drop table时内部表会将hdfs上的数据也删掉,而外部表仅仅是删除表的元数据,原始数据不会删除。

Hive 外表的优点

1、安全;外部表不用担心表删除带来的风险。在Hive当中,对于外部表来说,我们在删除表数据的时候,删除的仅仅是表的元数据信息,却不能删除掉表中的真实数据。
2、灵活;方便数据共享,使用更加灵活。

操作示例

1、外部数据展示

hive> dfs -ls/dw/im/prod/sessionContent;
Found 7 items
drwxr-xr-x   - icosc  hadoop          0 2018-11-07 23:55 /dw/im/prod/sessionContent/2018-11-07
drwxr-x--x   - hadoop hadoop          0 2018-11-08 23:55 /dw/im/prod/sessionContent/2018-11-08
drwxr-x--x   - hadoop hadoop          0 2018-11-09 23:55 /dw/im/prod/sessionContent/2018-11-09
drwxr-x--x   - hadoop hadoop          0 2018-11-10 23:55 /dw/im/prod/sessionContent/2018-11-10
drwxr-x--x   - hadoop hadoop          0 2018-11-11 23:55 /dw/im/prod/sessionContent/2018-11-11
drwxr-x--x   - hadoop hadoop          0 2018-11-12 23:55 /dw/im/prod/sessionContent/2018-11-12
drwxr-x--x   - hadoop hadoop          0 2018-11-13 13:55 /dw/im/prod/sessionContent/2018-11-13
hive>

2、创建Hive外表
根据数据的存放位置,在建表 sql 中指定 location。

usetemp;create external table tmp_im_session_content(`eventType` string comment"会话类型",`channelId`intcomment"渠道 id",`sourceType`intcomment"",`sessionId` string COMMENT"会话session id",`cId` string COMMENT"会话 id",`userId` string COMMENT"用户id",`vccId` string COMMENT"企业 id",`total`intCOMMENT"",`index`intCOMMENT'标识本次是第几次发送会话内容,从1开始 (每次最多发送10条聊天内容)',`content` array<struct<`from`:int,`to`:int,content:string,msgtype:int,`sequence`:bigint,createtime:bigint,errorcode:int,errorstring:string,status:int>>COMMENT'会话内容')
  PARTITIONED BY(`date` string)
  location "/dw/im/prod/sessionContent"
  TBLPROPERTIES ("comment"="IM 会话内容 by gz");

3、数据装载和验证
虽然在建表的时候已经指定了location,但是我们去查的时候,发现并没有数据。

hive>select> a.*>fromtemp.tmp_im_session_content a
    >where`date`='2018-11-07'>limit40;
OK
Time taken: 0.107 seconds
hive>

这是因为虽然在HDFS当中数据已经存在了,但是在Hive的元数据仓库中并没有,所以我们查不到数据。

4、给Hive外表装载数据

-- 创建分区并指定 locationaltertabletemp.tmp_im_session_content addifnotexistspartition(`date`='2018-11-07') location '/dw/im/prod/sessionContent/2018-11-07';-- 验证数据select
eventType,
channelId,
sourceType,
sessionId,
cId,
userId,
vccId,
total,index,
content
fromtemp.tmp_im_session_content a 
where`date`='2018-11-07'limit40;select
a.*fromtemp.tmp_im_session_content a 
where`date`='2018-11-07'limit40;-- 验证 ok

5、修复分区
Hive提供了一个"Recover Partition"的功能。原理相当简单,执行后,Hive会检测如果HDFS目录下存在,但表的metastore中不存在的partition元信息,更新到metastore中。如下:

msck repair tabletemp.tmp_im_session_content;

6、问题
执行查询还是没数据。

hive>select> a.*>fromtemp.tmp_im_session_content a
    >where`date`='2018-11-08'>limit40;
OK
Time taken: 0.107 seconds
hive>

这里就不得不说源数据存放的格式了。我创建的外表分区字段是date,但是我们的源文件路径是/dw/im/prod/sessionContent/2018-11-08,按照分区目录的格式应该是/dw/im/prod/sessionContent/date=2018-11-08。因此,用修复命令没起作用。这就要求在写 HDFS 的时候做好格式约定,避免后续各种意想不到的惊喜。
这个问题,可以通过下面 load data inpath 一节了解更详细的内容。

7、load data inpath 装载数据
命令如下:

loaddata inpath '/dw/im/prod/sessionContent/2018-11-08' overwrite intotabletemp.tmp_im_session_content PARTITION(`date`='2018-11-08');

看下源文件状态:

hive> dfs -ls/dw/im/prod/sessionContent/
    > ;
Found 7 items
drwxr-xr-x   - icosc  hadoop          0 2018-11-07 23:55 /dw/im/prod/sessionContent/2018-11-07
drwxr-x--x   - hadoop hadoop          0 2018-11-09 23:55 /dw/im/prod/sessionContent/2018-11-09
drwxr-x--x   - hadoop hadoop          0 2018-11-10 23:55 /dw/im/prod/sessionContent/2018-11-10
drwxr-x--x   - hadoop hadoop          0 2018-11-11 23:55 /dw/im/prod/sessionContent/2018-11-11
drwxr-x--x   - hadoop hadoop          0 2018-11-12 23:55 /dw/im/prod/sessionContent/2018-11-12
drwxr-x--x   - hadoop hadoop          0 2018-11-13 14:35 /dw/im/prod/sessionContent/2018-11-13
drwxr-x--x   - hadoop hadoop          0 2018-11-08 23:55 /dw/im/prod/sessionContent/date=2018-11-08

发现什么没?原来的目录

/dw/im/prod/sessionContent/2018-11-09

的目录不见了,但是多了一个

/dw/im/prod/sessionContent/date=2018-11-08

的目录。
前面我们提到,如果分区很多的时候,可以通过

msck repair table tableName

的方式来修复,但是如果格式不是 Hive 标准的分区文件存储格式,这个命令就没什么卵用。从刚刚的load data命令我们也可以看出,此命令会移动数据文件,如果不是标准的文件存储路径,也会根据命令进行相应的调整。这一点很重要。

如果需要传递日期变量,可以按如下操作:

-- 针对标准的分区文件,即显示的按照分区字段存放的数据文件loaddata inpath '/dw/im/prod/sessionContent/date=${date}' overwrite intotabletemp.tmp_im_session_content PARTITION(`date`='${date}');

OR

-- 针对非标准的,未显示按照分区字段存放的数据文件loaddata inpath '/dw/im/prod/sessionContent/${date}' overwrite intotabletemp.tmp_im_session_content PARTITION(`date`='${date}');

分区管理

从最前面 HDFS 文件可以看到,还有还6个日期目录,我可以创建5个 alterr table 的语句来装载数据。但是,如果有更多数据需要加载的情况,需考虑其他自动化方式:
1、shell 循环创建
这种方式已经写过,不再赘述,故而此处省略。
2、load data 方式加载数据
只要load data,数据都会被移动到表的location下面。

删除外表分区管理

-- 删除分区altertabletemp.tmp_im_session_content droppartition(date=`2018-11-07`);

总结

由于我们的源数据目录没有显示的指定分区字段,因此建表的时候没有指定 location,通过 load data inpath 命令来装载数据。
1、load data 命令会移动数据
2、load data inpath … overwrite 命令使用不当会导致数据被覆盖。
3、通过 alter table 的方式装载数据,会将源文件与对应的 Hive 表仓库进行映射,但是不会移动数据,不会改变目录。

标签: hive 数据仓库

本文转载自: https://blog.csdn.net/zhr2415658919/article/details/134813214
版权归原作者 耗子背刀PK猫 所有, 如有侵权,请联系我们删除。

“Hive外表创建和加载数据”的评论:

还没有评论