Hive 中内部表/外部表,分区表,分桶表

1.内部表/外部表
管理表(内表,也叫托管表),外部表(外表):建表时,有EXTERNAL关键字的就是外部表。在DROP TABLE时,外表的数据是不会被删除的,内表的数据会被删除,但两者对应的元数据(metadata)是都会被删除的
如果数据只是给Hive用,那么建议建立内表
如果数据还可能会给Hive以外的程序使用,或者数据本身就是Hive以外的程序建立的,Hive只是共享使用,对于这两种场景则建议建立外表

区别:
内部表数据由Hive自身管理,外部表数据由HDFS管理;
内部表数据存储的位置hive.metastore.warehouse.dir(默认:/user/hive/warehouse),外部表数据的存储位置由自己制定;
删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除;
对内部表的修改会将修改直接同步给元数据,而对外部表的表结构和分区进行修改,则需要修复(MSCK REPAIR TABLE table_name;)

外表可以指定路径:
create external table demo (
id int,
name string,
salary double
)
row format delimited
fields terminated by ‘\t’
location ‘/user/wangliming/hive/user_info’;

2.分区表与动态分区
Hive在查询时通常是做全表扫描的,而一个好的分区设计可以避免全表扫描并且可以大大减少Hive的扫描数据量
最常见的分区表是按天建立分区(当然也有使用时间空间两个维度进行分区的,第一个分区是按天建立的,第二个则按地区建立)
分区本质上就是一层目录
当然,分区也不能过多,否则就会大大增加NameNode的压力(Hadoop HDFS更适合存储与处理少量的大文件而不是大量的小文件),这时候一般就会结合使用分桶机制
分区是一种特殊的列,这种列的值不在数据文件中,而是通过目录名称读取的,分区实际上正对应了HDFS中的目录

create table access_log (
id int,
name string,
url string
)
partitioned by (dt string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ‘\t’ ;

退出hive
vi access_log
1 百度 http//:www.baidu.com
2 腾讯 http//:www.qq.com
3 谷歌 http//:www.geogle.com

进入hive
use wangliming;

load data local inpath ‘/home/wangliming/hive/access_log’ into table access_log partition(dt=‘20181106’);

select * from access_log where dt=‘20181106’ limit 10; – 标准查询

insert into table access_log
partition(dt=‘20181108’)
select * from (
select 1,‘百度’,‘http://www.baidu.com
union all
select 2,‘腾讯’,‘http://www.qq.com
union all
select 3,‘谷歌’,‘http://www.baidu.com
)t;

查看某张表有哪些分区
show partitions access_log;

动态分区(默认关闭,使用静态分区)
set hive.exec.dynamic.partition=true; (必须保证有一个静态分区。通常第一个)
set hive.exec.dynamic.partition.mode=nonstrict; (所有分区都可以为动态)

动态分区第一种情况(set hive.exec.dynamic.partition=true; 默认值为false)(必需起别名)
insert into table access_log_2
partition(dt=‘20181106’,province)
select uid,name,url,province from (
select 1 as uid,‘百度’ as name,‘http://www.baidu.com’ as url,‘ShanDong’ as province
union all
select 2 as uid,‘腾讯’ as name,‘http://www.qq.com’ as url,‘HeiBei’ as province
union all
select 3 as uid,‘谷歌’ as name,‘http://www.geogle.com’ as url,‘AnHui’ as province
)t;

动态分区第二种情况(set hive.exec.dynamic.partition.mode=nonstrict; 默认值为strict )
insert into table access_log_2
partition(dt,province)
select uid,name,url,dt,province from (
select 1 as uid,‘百度’ as name,‘http://www.baidu.com’ as url,‘20181107’ as dt,‘ShanDong’ as province
union all
select 2 as uid,‘腾讯’ as name,‘http://www.qq.com’ as url,‘20181108’ as dt,‘HeiBei’ as province
union all
select 3 as uid,‘谷歌’ as name,‘http://www.geogle.com’ as url,‘20181109’ as dt,‘AnHui’ as province
)t;

3.分桶表(详尽版)
分区不能过多,否则就会大大增加NameNode的压力(Hadoop HDFS更适合存储与处理少量的大文件而不是大量的小文件),这时候一般就会结合使用分桶机制
分桶可以使数据均匀分布,避免了创建大量小文件的情景;提高了查询效率(尤其是连接查询map side join);另外分桶表也特别适用于抽样查询场景
桶的数量一般对应reducer的数量,因为有时候虽然没有reducer,但是最终的结果也依然会分桶
分区对应的字段实际上是目录,不会存储在数据文件中,但是分桶对应的字段就是实际的数据字段

创建一个分区分桶表
CREATE TABLE mb(
uid int,
id int,
name string,
url string)
PARTITIONED BY (
dt string)
CLUSTERED BY (
uid)
INTO 3 BUCKETS
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ‘\t’ ;

以下属性必须设置为true
set hive.enforce.bucketing=true;
否则,我们需要设置和分桶个数相匹配的Reducer数目,如set mapred.reduce.tasks=3,并且查询的时候需要添加cluster by 子句

退出hive
vi access_log_bucket
10000 1 刘十三 http://www.baidu.com/
10001 2 张三 http://www.le.com/
10002 3 李四 http://www.google.com/
10003 4 王五 http://www.ip138.com/
10004 5 赵六 http://www.qq.com/
10005 6 小明 http://www.qq.com/
10006 7 小红 http://www.qq.com/
10007 8 小强 http://www.qq.com/
10008 9 小刚 http://www.qq.com/
10009 10 小小 http://www.qq.com/

进入hive
use liuhongliang;
load data local inpath ‘access_log_bucket’ overwrite into table mb partition (dt=20181107);

dfs -ls /apps/hive/warehouse/liuhongliang.db/mb/dt=20181107;
下面只有一个数据文件’access_log_bucket
因为load只是简单的复制文件,不会触发MR Job,所以使用load方式导入的数据不会被自动分桶

insert overwrite table mb
partition(dt=20181106)
select uid, id, name, url
from mb
where dt=20181107;

dfs -ls /apps/hive/warehouse/liuhongliang.db/mb/dt=20181106;
dfs -cat /apps/hive/warehouse/liuhongliang.db/mb/dt=20181106/000000_0;
我们发现,虽然分区下面有三个文件(3个桶),但实际上数据依然没有分桶,所有数据还是只存储在第一个文件中

insert overwrite table mb
partition(dt=20181105)
select uid, id, name, url
from mb
where dt=20181107
cluster by uid;

dfs -ls /apps/hive/warehouse/liuhongliang.db/mb/dt=20181105;
dfs -cat /apps/hive/warehouse/liuhongliang.db/mb/dt=20181105/000002_0;
这时,数据才会真正分桶

insert overwrite table mb
partition(dt=20181104)
select uid, id, name, url
from mb
where dt=20181105;

dfs -ls /apps/hive/warehouse/liuhongliang.db/mb/dt=20181104;
dfs -cat /apps/hive/warehouse/liuhongliang.db/mb/dt=20181104/000000_0;
使用load方式导入的数据肯定不会自动分桶,然而使用select方式导入的数据也不一定会自动分桶,所以我们应该使用cluster by来保证分桶,但如果我们不使用cluster by,就必须保证select的数据的来源必须是经过真正分桶的,或者像下面这样,数据是来源于一系列计算的最终结果的

insert overwrite table mb
partition(dt=20181103)
select * from (
SELECT 10010, 1, ‘小红’, ‘http://www.baidu.com/
union all
SELECT 10011, 3, ‘小强’, ‘http://www.google.com/
union all
SELECT 10012, 2, ‘小明’, ‘http://www.sogou.com/
)t;

dfs -ls /apps/hive/warehouse/liuhongliang.db/mb/dt=20181103;
dfs -cat /apps/hive/warehouse/liuhongliang.db/mb/dt=20181103/000000_0;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值