案例详解__HIVE中内部表、外部表、分区表和分桶表

目录
一、Hive建表语法
二、内部表外部表
三、分区表
四、分桶表

Hive在建表时可指定内部表、外部表、分区表和分桶表,所以在学习这四种表之前,先一起了解Hive建表语法

一、Hive建表语法

Hive建表方式共有三种:直接建表法、查询建表法、like建表法,下面讲解直接建表法

’[]’ 表示可选,’|’ 表示二选一

创建表的语句:
Create [EXTERNAL] TABLE [IF NOT EXISTS] table_name 
//EXTERNAL 关键字可以让用户创建一个外部表,如果不指定关键字EXTERNAL则为内部表
//如:create table IF NOT EXISTS test_bucket
[(col_name data_type [COMMENT col_comment], ...)] 
//col_nam表字段,data_type字段类型,[COMMENT col_comment]字段注释 , ...为其他字段
//如:(word string,num bigint )
[COMMENT table_comment] 
//表注释,COMMENT关键字,table_comment表解释具体内容
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)] 
//PARTITIONED BY分区
[CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC],...)]INTO num_buckets BUCKETS]
//分桶,通过 clustered by(字段名) into bucket_num buckets 分桶,意思是根据字段名分成bucket_num个桶
//如:clustered by(id) into 4 buckets
[ROW FORMAT row_format] 
//加载数据文件到hive表时,数据文件字段于字段的分隔符
//如:row format delimited fields terminated by '\t'
[STORED AS file_format] 
[LOCATION hdfs_path]
//指定表存放的HDFS位置,如果不指定存放在默认路径,内部表默认路径/user/hive/warehouse
建表语句解释:
  • CREATE TABLE 创建一个指定名字的表。

  • EXTERNAL 关键字可以让用户创建一个外部表,无EXTERNAL 关键字则为内部表。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。

  • 有分区的表可以在创建的时候使用 PARTITIONED BY 语句。一个表可以拥有一个或者多个分区,每一个分区单独存在一个目录下。

案例:
//01-创建orders_part外部表
create  EXTERNAL table orders_part(
order_id string comment '订单编号',
user_id string comment '客户号',
order_number string  comment '订单数量',
order_date string comment '下单时间'
)
comment '测试_创建orders_part表'
partitioned by(order_date string)
row format delimited fields terminated by ','

//02-创建分桶表
create table test_bucket (
id int comment 'ID', 
name string comment '名字'
)
comment '测试分桶'
clustered by(id) into 4 buckets
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

二、内部表外部表

通过建表语句、location位置、删除表三方面来学习外部表,内部表

1、建表语句

1.1、内部表
平时创建的普通表为内部表

create table `test_internal` (
id string comment 'ID', 
name string comment '名字'
)
comment '测试内部表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

1.2、外部表
external关键字的为外部表

create external table `test_external` (
id string comment 'ID', 
name string comment '名字'
)
comment '测试外部表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

仅从建表语句上看,内部表和外部表的区别为是否带有external关键字

2、location

网上很多博客写的外部表建表语句中都带有location关键字,我这里单独分开来写。[我参考的是一个博主的文章]

  • 其实不管是内部表还是外部表可以加location关键字指定hive表的存储路径,当然也可以不加,从这点看是无区别的。

  • 如果不加location那么不管是内部表还是外部表会在默认的hive配置的hdfs路径下下新建一个和表名相同的文件夹。内部表默认存放路径:/user/hive/warehouse

  • 如果加了location指定另外的文件夹,那么在查询时,该文件夹下对应的数据会加载到hive表里。

如果不理解上面文字描述可以看下面案例

案例:
01、准备数据

将数据上传到HDFS

//data.txt 数据
001,张三
002,李四
003,王五
hadoop fs -mkdir -p /tmp/hive_test/internal_location //创建Hdfs目录
hadoop fs -mkdir -p /tmp/hive_test/external_location
hadoop fs -put data.txt /tmp/hive_test/internal_location  //上传数据到HDFS
hadoop fs -put data.txt /tmp/hive_test/external_location //上传数据到HDFS文件夹

02、建表

内部表

create table IF NOT EXISTS test_internal_location (
id string comment 'ID', 
name string comment '名字'
)
comment '测试内部表location'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
location '/tmp/hive_test/internal_location';

外部表

create external table   IF NOT EXISTS test_external_location (
id string comment 'ID', 
name string comment '名字'
)
comment '测试外部表location'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
location '/tmp/hive_test/external_location';

说明:hdfs 文件夹及对应下的数据和建表语句没有先后顺序,建表在前和在后都可以把数据加载出来,如果先建表的话,对应的文件夹如果不存在,则会自动建立文件夹。

3、删除表

内部表和外部表的区别主要体现在删除表,将上面建立的2个表都删掉。

drop table test_internal_location;
drop table test_external_location;

看一下对应的hdfs路径有啥变化


发现外部表external_location文件夹存在,而内部表文件夹没了,这也就是内部表和外部表的区别

内部表删除表时,对应的hdfs的路径下的文件会删掉;外部表删除表时,对应的HDFS的路径下的文件则不会删掉。

4、内部表外部表—总结

(1) 建表:带有external关键字为外部表,否则为内部表
(2) location:内部表和外部表建表时都可以自己指定location
(3) 删除表:外部表不会删除对应的数据,只会删除元数据信息,内部表则会删除元数据信息和对应的数据。

参考文章:Hive内部表和外部表,看了这个博主写的两篇文章,写得真的很好很好。

三、分区表

分区表一般在数据量比较大,且有明确的分区字段时使用,这样用分区字段作为查询条件查询效率会比较高。Hive分区分为静态分区动态分区

1、为什么出现分区表?

假设有海量的数据保存在hdfs的某一个hive表名对应的目录下,使用hive进行操作的时候,往往会搜索这个目录下的所有的文件,这时会非常耗时。(hive表对应hdfs目录下的文件数据都会被加载到hive表中)

如果我们知道这些数据的某些特征,然后使用Hive进行操作的时候,就可以在where子句种对这些特征进行过滤,那么对数据的操作就会在符合条件子目录下进行,其他不符合条件目录下的内容就不会被读取

在数据量非常大的时候,这样节省大量的时间,这种把表种的数据分散到子目录下的方式就是分区表。



下面我们还是通过实战来学习分区表

案例

2、创建分区表

静态分区和动态分区的建表语句是一样的

create table test_partition (
name string comment '名字',
age int comment '年龄'
)
comment '测试分区'
partitioned by (provice string comment '省',city string comment '城市')
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

用partitioned by指定创建的分区,多个分区意味着多级目录。

创建之后hdfs上的目录结构并不会立即发生变化,因为此时表中还没有数据,往表中插入数据之后,会发现在表名对应的目录下,会多出两级目录。

3、插入语句

静态分区和动态分区的插入数据的语法是不一样的,下面讲解静态分区
想学习动态分区可看这篇文章hive使用动态分区插入数据详解

3.1 静态分区

静态分区是在语句中指定分区字段为某个固定值

3.1.1 静态分区加载数据-INSERT INTO语法
insert into table test_partition partition(provice = "hebei",city = "baoding") values ('张三',20);
insert into table test_partition partition(provice = "hebei",city = "baoding") values ('张三',20);
insert into table test_partition partition(provice = "hebei",city = "baoding") values ('李四',20);

insert into table test_partition partition(provice = "hebei",city = "handan") values ('张三',20);
insert into table test_partition partition(provice = "hebei",city = "handan") values ('张三',20);
insert into table test_partition partition(provice = "hebei",city = "handan") values ('李四',20);
3.1.2 静态分区加载数据-LOAD DATA方法

data4.txt

张三,23
李四,23
王五,23

加载本地文件到hive表中

load data local inpath '/home/study/data4.txt' into table test_partition partition (provice = "hebei",city = "handan");
load data local inpath '/home/study/data4.txt' into table test_partition partition (provice = "hebei",city = "handan");
load data local inpath '/home/study/data4.txt' into table test_partition partition (provice = "sichuan",city = "chengdu");

3.1.3 查看数据

hive的仓库路径: /user/hive/warehouse
数据库名称: myhive.db myhive
表名: test_partition
分区字段名:provice,city

总结:

  • (1) 分区表的意思,其实想明白了就很简单。就是在系统上建立文件夹,把分类数据放在不同文件夹下面,加快查询速度。

  • (2) 关键点1:partitioned by (provice String,city string); 创建表格时,指明了这是一个分区表。将建立双层目录,第一次目录的名字和第二层目录名字规则
    PARTITIONED BY子句中定义列,是正式的列,成为分区列。但是数据文件中并没有这些值,仅代表目录

  • (3) 关键点2:partition (provice = "hebei",city = "handan"); 上传数据时,把数据分别上传到不同分区中。也就是分别放在不同的子目录下。

参考文章1:Hive分区表学习总结
参考文章2:hive使用动态分区插入数据详解
参考文章3:HIVE-分区表详解以及实例

四、分桶表

其实分区和分桶这两个概念对于初学者来说是比较难理解的,要想更好的学习分桶表,看文章的同时还需要自己操作才行。下面我们通过实操来学习分桶表[可能刚看着代码有点迷惑,不过做到后面就理解了]

也可以像我这样学习:看文章+实操+写文章总结,很多知识点我按这样学习后基本上不会忘记。

1、分桶简介?

分桶规则:桶是通过对指定列进行哈希计算来实现的,对分桶字段值进行哈希,哈希值除以桶的个数求余,余数决定了该条记录在哪个桶中,也就是余数相同的在一个桶中。
优点:1、提高join查询效率 2、提高抽样效率

2、分桶操作

2.1、创建桶表:

通过 clustered by(字段名) into bucket_num buckets 分桶,意思是根据字段名分成bucket_num个桶

create table test_bucket (
id int comment 'ID', 
name string comment '名字'
)
comment '测试分桶'
clustered by(id) into 4 buckets
-- 注意分桶字段只能是建表中已有的字段,
-- 而分区表的字段必须是建表中没有的字段
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

2.2、设置Hive的分桶开关

打开Hive客户端,并在会话终端开启Hive分桶的开关:set hive.enforce.bucketing=true;(此设置为临时设置,一旦退出会话终端,再打开就会恢复默认设置false)

set hive.enforce.bucketing=true;  ///强制分桶

此开关打开之后,会自动根据bucket(桶)个数自动分配Reduce task个数,Reduce个数与bucket个数一致。(此外,Reduce的个数还可以通过mapred.reduce.tasks进行设置,但是这方法不推荐在Hive分桶中使用)

2.2.3、load data方法插入数据到分桶表

buckt_data.txt

1,name1
2,name2
3,name3
4,name4
5,name5
6,name6
7,name7
8,name8
9,name9

load data 插入数据到分桶表

load data local inpath '/home/study/buckt_data.txt' into table test_bucket ;


我们看到虽然设置了强制分桶,但实际test_bucket 表下面只有一个test_bucket 一个文件。直接load data不会分桶的效果,这样和不分桶一样,在HDFS上只有一个文件。需要借助中间表才能实现

2.2.3、借用中间表insert into方法插入数据到分桶表

创建中间表

create table test (
id int comment 'ID', 
name string comment '名字'
)
comment '测试分桶中间表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;

先将数据load到中间表

load data local inpath '/home/study/buckt_data.txt' into table test;

通过下面insert into的语句,将中间表的数据插入到分桶表中,这样会产生四个文件。

insert into test_bucket select * from test;
借的别人的图片,不过这个博主写的文章真的好

从上面图片可以看见:
(1) 是以文件的形式存在的,而不是像分区那样以文件夹的形式存在。
(2) 除以4余数相同的确实在一个文件里,也就是在一个桶中

总结:

(1) 其实桶的概念就是MapReduce的分区的概念,两者完全相同。物理上每个桶就是目录里的一个文件,一个作业产生的桶(输出文件)数量和reduce任务个数相同。
(2) 桶是按照数据内容的某个值进行分桶,把一个大文件散列称为一个个小文件。
(3) 这些小文件可以单独排序。如果另外一个表也按照同样的规则分成了一个个小文件。两个表join的时候,就不必要扫描整个表,只需要匹配相同分桶的数据即可。效率当然大大提升。
同样,对数据抽样的时候,也不需要扫描整个文件。只需要对每个分区按照相同规则抽取一部分数据即可。

参考文章1:Hive分桶表学习总结
参考文章2:HIVE-分桶表的详解和创建实例
参考文章3:Hive分桶表的使用场景以及优缺点分析,想了解概念看该篇文章

关于HIVE中内部表、外部表、分区表和分桶表就总结完了,后期还得继续努力学习呀.问题还是得一个一个的解决.加油啦~~~
做仰卧起坐去了,周末愉快啦.
这个冬天真冷

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容