hive详细笔记(四)-Hive内部表,外部表,分区表,分桶表详解(附带讲解视频)

本节目录

  1. 内部表和外部表

  2. 静态分区表

  3. 动态分区表 

  4. 分桶表

  5. 抽样查询

1 内部表和外部表

未被external修饰的是内部表(managed table),被external修饰的为外部表(external table);
区别:
内部表数据由Hive自身管理,外部表数据由HDFS管理;
内部表数据存储的位置是hive.metastore.warehouse.dir(默认:/user/hive/warehouse),

外部表数据的存储位置由自己制定(如果没有LOCATION,Hive将在HDFS上的/user/hive/warehouse文件夹下以外部表的表名创建一个文件夹,并将属于这个表的数据存放在这里);
删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除;
对内部表的修改会将修改直接同步给元数据,而对外部表的表结构和分区进行修改,则需要修复(MSCK REPAIR TABLE table_name;)
应用场景

对于一些公共的数据源使用外部表. 对于保存的一些业务维度表或者是统计好的报表使用管理表(内部表)

1.1 内部表

---  默认的内部表  删除表会删除数据 
create table  if not exists tb_product1(
id  int ,
name string ,
price double ,
cate string  COMMENT '类别',
pnum int ,
description string
)
row format delimited fields terminated by "," 
location "/ppp"
;

create table  if not exists tb_product2(
id  int ,
name string ,
price double ,
cate string  COMMENT '类别',
pnum int ,
description string
)
row format delimited fields terminated by "," 
location "/ppp"
;
 rows affected (0.202 seconds)
0: jdbc:hive2://linux01:10000> select * from tb_product1 ;
OK
+-----------------+-------------------+--------------------+-------------------+-------------------+--------------------------+
| tb_product1.id  | tb_product1.name  | tb_product1.price  | tb_product1.cate  | tb_product1.pnum  | tb_product1.description  |
+-----------------+-------------------+--------------------+-------------------+-------------------+--------------------------+
| 1001            | 联想笔记本             | 4500.0             | 电脑                | 100               | 还行                       |
| 1002            | 苹果笔记本             | 14500.0            | 电脑                | 3000              | 凑合                       |
| 1003            | IBM笔记本            | 9500.0             | 电脑                | 10                | 不好用.散热不好;声卡不好            |
| 1004            | 戴尔笔记本             | 8500.0             | 电脑                | 120               | 散热不好                     |
| 1005            | 小米手机              | 1500.0             | 手机                | 300               | 卡顿                       |
| 1006            | 华为手机              | 4500.0             | 手机                | 100               | 散热不好                     |
| 1007            | 苹果手机              | 5500.0             | 手机                | 110               | 不能支付                     |
| 1008            | oppo手机            | 2500.0             | 手机                | 98                | 没用过                      |
| 1009            | 诺基亚手机             | 500.0              | 手机                | 100               | 神机                       |
+-----------------+-------------------+--------------------+-------------------+-------------------+--------------------------+
9 rows selected (0.281 seconds)
0: jdbc:hive2://linux01:10000> select * from tb_product2 ;
OK
+-----------------+-------------------+--------------------+-------------------+-------------------+--------------------------+
| tb_product2.id  | tb_product2.name  | tb_product2.price  | tb_product2.cate  | tb_product2.pnum  | tb_product2.description  |
+-----------------+-------------------+--------------------+-------------------+-------------------+--------------------------+
| 1001            | 联想笔记本             | 4500.0             | 电脑                | 100               | 还行                       |
| 1002            | 苹果笔记本             | 14500.0            | 电脑                | 3000              | 凑合                       |
| 1003            | IBM笔记本            | 9500.0             | 电脑                | 10                | 不好用.散热不好;声卡不好            |
| 1004            | 戴尔笔记本             | 8500.0             | 电脑                | 120               | 散热不好                     |
| 1005            | 小米手机              | 1500.0             | 手机                | 300               | 卡顿                       |
| 1006            | 华为手机              | 4500.0             | 手机                | 100               | 散热不好                     |
| 1007            | 苹果手机              | 5500.0             | 手机                | 110               | 不能支付                     |
| 1008            | oppo手机            | 2500.0             | 手机                | 98                | 没用过                      |
| 1009            | 诺基亚手机             | 500.0              | 手机                | 100               | 神机                       |

删除procut1 表 由于内部表 所以会删除  /ppp文件夹

导致 product2表中没有数据

1.2 外部表

扫描二维码关注公众号,回复: 11330751 查看本文章
create external table  if not exists tb_product11(
id  int ,
name string ,
price double ,
cate string  COMMENT '类别',
pnum int ,
description string
)
row format delimited fields terminated by "," 
location "/xxx"
;

create external table  if not exists tb_product22(
id  int ,
name string ,
price double ,
cate string  COMMENT '类别',
pnum int ,
description string
)
row format delimited fields terminated by "," 
location "/xxx"
;

其中删除product11 表数据并没有删除

1.3  查看表类型

desc formatted student2;
Table Type:             MANAGED_TABLE  -- 内部表

 desc formatted student2;
Table Type:             EXTERNAL_TABLE -- 外部表

1.4 内部表和外部表互换

alter table student2 set tblproperties('EXTERNAL'='FALSE');

注意 'EXTERNAL'='FALSE'区分大小写

2 分区表

数据分区的概念以及存在很久了,通常使用分区来水平分散压力,将数据从物理上移到和使用最频繁的用户更近的地方,以及实现其目的。

hive中处理的数据在HDFS中 , select * from tb_name where dt=2020-06-18 ;
查询表中的数据是加载HDFS中对应表文件夹下的数据 ,文件夹下的数据很多,将数据全部加载以后再筛选过滤出数据, 显然效率低 ,Hive中的分区表起始就是根据某中维度将数据分文件夹管理 ,当安装这种维度查询的时候,直接从对应的文件夹下加载数,效率更高!     
   
               

 hive中有分区表的概念,我们可以看到分区具重要性能优势,而且分区表还可以将数据以一种符合逻辑的方式进行组织,比如分层存储

分区表分别有静态分区和动态分区 !
 

2.1 静态分区表

2.1.1 一级分区

数据如下 : 每天产生的订单数据在不同的文件中

06-18.txt
01,2020-06-18,200
02,2020-06-18,200
03,2020-06-18,100
03,2020-06-18,200
04,2020-06-18,200
05,2020-06-18,20
06,2020-06-18,100
07,2020-06-18,200
08,2020-06-18,200
09,2020-06-18,100
10,2020-06-18,200
06-19.txt
11,2020-06-19,20
14,2020-06-19,200
15,2020-06-19,20
16,2020-06-19,100
17,2020-06-19,200
18,2020-06-19,200
19,2020-06-19,100
12,2020-06-19,200
13,2020-06-19,100
13,2020-06-19,200

如果没有分区

--建表
create table  tb_order2(
oid int ,
dt string ,
cost double 
)
row format delimited fields terminated by "," ;
--加载每天的数据到表中
load data local inpath "/hive/data/06-18.txt" into table  tb_order2 ;
load data local inpath "/hive/data/06-19.txt" into table  tb_order2 ;
对应的数据会被加载到表对应的文件夹中 ,当我们执行如下查询的时候 ,先加载两个文件数据,再过滤
select * from tb_order where dt='2020-06-18' ; --两个文件

静态分区

create table  tb_p_order(
oid int ,
dt string ,
cost double 
)
partitioned  by (dy string)
row format delimited fields terminated by "," ;


load data local inpath "/hive/data/06-18.txt" into table  tb_p_order  partition(dy="06-18");
load data local inpath "/hive/data/06-19.txt" into table  tb_p_order  partition(dy="06-19");
	
	0: jdbc:hive2://linux01:10000> select * from tb_p_order where  dy="06-18";
+-----------------+----------------+------------------+----------------+
| tb_p_order.oid  | tb_p_order.dt  | tb_p_order.cost  | tb_p_order.dy  |
+-----------------+----------------+------------------+----------------+
| 1               | 2020-06-18     | 200.0            | 06-18          |
| 2               | 2020-06-18     | 200.0            | 06-18          |
| 3               | 2020-06-18     | 100.0            | 06-18          |
| 3               | 2020-06-18     | 200.0            | 06-18          |
| 4               | 2020-06-18     | 200.0            | 06-18          |
| 5               | 2020-06-18     | 20.0             | 06-18          |
| 6               | 2020-06-18     | 100.0            | 06-18          |
| 7               | 2020-06-18     | 200.0            | 06-18          |
| 8               | 2020-06-18     | 200.0            | 06-18          |
| 9               | 2020-06-18     | 100.0            | 06-18          |
| 10              | 2020-06-18     | 200.0            | 06-18          |
+-----------------+----------------+------------------+----------------+

查看HDFS中数据存储

2.1.2 二级分区

将数据按照层级关系再细分 比如 年为一级分区  年下面有月分区

create table tb_partition2(
id int ,
name string ,
gender string ,
birthday string 
)
partitioned  by (y string , m string)
row format delimited fields terminated by "," ;
			   
a.txt
1001,ls,M,90-01-05
1002,zs,M,90-01-06
1003,ww,F,90-01-07

b.txt
1001,ls2,M,90-02-05
1002,zs2,M,90-02-06
1003,ww2,F,90-02-07

c.txt
1001,ls2,M,95-02-05
1002,zs2,M,95-02-06
1003,ww2,F,95-02-07

d.txt
1001,ls2,M,95-03-05
1002,zs2,M,95-03-06
1003,ww2,F,95-03-07


load data local  inpath "/hive/data/a.txt"  into  table tb_partition2 partition(y='90',m='01');
load data local  inpath "/hive/data/b.txt"  into  table tb_partition2 partition(y='90',m='02');
load data local  inpath "/hive/data/c.txt"  into  table tb_partition2 partition(y='95',m='02');
load data local  inpath "/hive/data/d.txt"  into  table tb_partition2 partition(y='95',m='03');

数据在HDFS 中的目录结构是这样的

/tb_partition2/
                /90/
                   /01
                   /02
                /95/
                   /02
                   /03    

2.2 动态分区表

上述是静态分区 , 静态分区是数据原本已经安装某维度保存在了不同的文件中了 , 如果想要根据查询的数据的某个属性进行分区 ,就是动态分区!

数据如下 ,想要根据性别, 或者是地理位置来进行分区,那么就是根据每个属性的值来进行分区的!!

user.txt
u001 ZSS 23 M beijing
u002 YMM 33 F nanjing
u003 LSS 43 M beijing
u004 ZY 23 F beijing
u005 ZM 23 M beijing
u006 CL 23 M dongjing
u007 LX 23 F beijing
u008 YZ 23 M beijing
u009 YM 23 F nanjing
u010 XM 23 M beijing
u011 XD 23 F beijing
u012 LH 23 M dongjing
u013 FTM 23 F dongjing

2.2.1 创建一个普通表   导入数据 

create  table  if not exists  tb_user(
uid string ,
name  string ,
age int ,
gender string ,
address string 
)
row format delimited fields  terminated by  " " ;
load  data local  inpath "/hive/data/user.txt"  into table  tb_user ;

2.2.2 创建分区表

create  table  if not exists  tb_p_user(
uid string ,
name  string ,
age int ,
gender string ,
address string 
)
partitioned  by (addr string)
row format delimited fields  terminated by  " " ;

2.2.3 开启动态分区功能

set hive.exec.dynamic.partition=true ;
set hive.exec.dynamic.partition.mode=nonstrick;  可以从普通表中导入数据

2.2.4 动态导入数据

普通表5个字段
分区表 5个主字段 1 个分区字段
插入数据的时候字段个数类型一致  最后一个字段就是分区字段 

insert into tb_p_user partition(addr)
select uid , name , age , gender , address , address from  tb_user ;

4 分桶表

对Hive(Inceptor)表分桶可以将表中记录按分桶键(字段)的哈希值分散进多个文件中,这些小文件称为桶。

分区针对的是数据的存储路径;分桶针对的是数据文件。

分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区,特别是之前所提到过的要确定合适的划分大小这个疑虑。

分桶是将数据集分解成更容易管理的若干部分的另一个技术。

把表或分区划分成bucket有两个理由

1,更快,桶为表加上额外结构,链接相同列划分了桶的表,可以使用map-side join更加高效。

2,取样sampling更高效。没有分区的话需要扫描整个数据集。

4.1 数据

将数据分文件存储  , 类似于分区
uid      name
1001    ss1
1002    ss2
1003    ss3
1004    ss4
1005    ss5
1006    ss6
1007    ss7
1008    ss8
1009    ss9
1010    ss10
1011    ss11
1012    ss12
1013    ss13
1014    ss14
1015    ss15
1016    ss16

4.2  创建分桶表 

create table if not exists  tb_cluster(
uid  int ,
name string
)
clustered by(uid) 
into  4  buckets 
row format  delimited fields terminated by "\t" ;

查看表的分桶信息

desc formatted tb_cluster ;
 
OK
+-------------------------------+----------------------------------------------------+-----------------------------+
|           col_name            |                     data_type                      |           comment           |
+-------------------------------+----------------------------------------------------+-----------------------------+

| Num Buckets:                  | 4                                                  | NULL                        |
| Bucket Columns:               | [uid]                                              | NULL                        |
+-------------------------------+----------------------------------------------------+-----------------------------+

4.3 创建普通表   导入数据到普通表中

create table if not exists  tb_cluster2(
uid  int ,
name string
)
row format  delimited fields terminated by "\t" ;
load  data local inpath "/hive/data/cluster.txt" into table  tb_cluster2 ;
+------------------+-------------------+
| tb_cluster2.uid  | tb_cluster2.name  |
+------------------+-------------------+
| 1001             | ss1               |
| 1002             | ss2               |
| 1003             | ss3               |
| 1004             | ss4               |
| 1005             | ss5               |
| 1006             | ss6               |
| 1007             | ss7               |
| 1008             | ss8               |
| 1009             | ss9               |
| 1010             | ss10              |
| 1011             | ss11              |
| 1012             | ss12              |
| 1013             | ss13              |
| 1014             | ss14              |
| 1015             | ss15              |
| 1016             | ss16              |
+------------------+-------------------+

4.4  开启分桶

set hive.enforce.bucketing=true; 
set mapreduce.job.reduces=-1;  

4.5  基于查询的方式将数据导入到分桶表中

insert  into table tb_cluster
select  uid , name from tb_cluster2 ;

4.6 原理

就是将数据按照指定的分桶字段进行hashcode%桶数 ,类似于MR程序中的数据分区

在HDFS文件系统中数据存储

5 抽样查询

对于非常大的数据集,有时用户需要使用的知识一个具有代表性的查询结果,而不是全部结果。Hive可以通过对表进行分桶抽样来满足这个需求。

5.1 分桶抽样 

select * from numbers TABLESAMPLE(BUCKET 3 OUT OF 10 ON number);
其中tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y) 。y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了64份,当y=32时,抽取(64/32=)2个bucket的数据,当y=128时,抽取(64/128=)1/2个bucket的数据。x表示从哪个bucket开始抽取。例如,table总bucket数为32,tablesample(bucket 3 out of 16),表示总共抽取(32/16=)2个bucket的数据,分别为第3个bucket和第(3+16=)19个bucket的数据。

5.2 数据库抽样 

Hive提供了另外一种按照抽样百分比进行抽样的方式,这种是基于行数的,按照输入路径下的数据块百分比进行抽样。

select * from numbersflat TABLESAMPLE(0.1 PERCENT) s;
这种抽样方式不一定适用于所有的文件格式。另外抽样的最小抽样单元是一个HDFS数据块。如果标的数据大小小于普通的块大小128MB,那么会返回所有的行。
 

抽样查询使用于hive中的任意表, 只不过分桶表抽样效率更高!!

猜你喜欢

转载自blog.csdn.net/qq_37933018/article/details/106875955