Hive分区表与分桶表的使用具体说明

Posted 雷神乐乐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive分区表与分桶表的使用具体说明相关的知识,希望对你有一定的参考价值。

目录

一、分区表

(一)分区表基本语法

1.创建分区表

2.往分区表中写入数据的两种方法

(1)load装载本地数据

(2)insert...select...(常用)

3.读取分区表数据

4. Hive分区表的存储路径规划:分区字段=分区值

5.分区表基本操作

(1)查看所有分区信息

(2)新增分区

(3)删除分区

6.修复分区

(1)add partition

(2)drop partition

(3)msck(metastore check)

(二)二级分区表

(三)动态分区

1.动态分区相关参数

二、分桶表

1.普通分桶表

2.分桶排序表

三、分区表和分桶表的区别


        分区表和分桶表涉及到了HQL优化:对底层数据的存储优化是分区表、分桶表、文件格式和压缩,另一种优化方式就是执行计划调参。分区表和分桶表没有必然的联系,二者是不同的概念。

一、分区表

        分区表十分重要。Hive中的分区(与MapReduce中的分区不是一个概念)就是把一张大表的数据按照业务需要分散地存储到多个目录,每个目录就称为该表的一个分区,在查询时通过where子句中的表达式选择查询所需要的分区,这样的查询效率会提高很多。 分区如果设计合理,将来查询的时候就可以避免全表扫描,而是定位到一个具体的目录。

(一)分区表基本语法

1.创建分区表

这里我们没有指定分区表的存储路径,就会存储在默认路径/opt/soft/hive312/warehouse目录下。

分区字段不可以选择表中的字段。

create table dept_partition
(
    deptno int,--部门编号
    dname  string,-- 部门名称
    loc    string-- 部门位置
) partitioned by (day string)    -- 分区字段,当做表中的字段
    row format delimited fields terminated by '\\t';

2.往分区表中写入数据的两种方法

源数据:

[root@lxm147 atguigu]# vim /opt/atguigu/dept_20220401.log 

10      行政部  1700
20      财务部  1800

(1)load装载本地数据

load data local inpath '/opt/atguigu/dept_20220401.log'
    into table dept_partition
    partition (day = '2023-02-20');

 查询结果

(2)insert...select...(常用)

需求:将2023-02-20分区中的数据写入到2022-04-02分区中。

这里用到insert和select,所以会用到mapReduce,速度会比较慢。需要指定mr运行在本地,而不是在yarn上。

-- 设置mr运行在本地
set mapreduce.framework.name=local;

insert overwrite table dept_partition partition (day = '2022-04-02')
select deptno,
       dname,
       loc
from dept_partition
where day = '2023-02-20';

 查询结果

3.读取分区表数据

查询分区表数据时,可以将分区字段看作表的伪列,可像使用其他字段一样使用分区字段。

select *
from dept_partition where day='2022-04-02';


select 
    deptno, 
    dname, 
    loc
from dept_partition
where day = '2023-02-20';

4. Hive分区表的存储路径规划:分区字段=分区值

分区中的字段是分区表的三个字段对应的内容

5.分区表基本操作

(1)查看所有分区信息

show partitions dept_partition;

(2)新增分区

新增分区后,hdfs上会创建路径,在Hive的元数据中新增一条分区信息

查看元数据中新增的分区信息:在mysql中存放hive元数据的数据库中的partitions表内

1)创建单个分区

alter table dept_partition add partition (day = '2023-01-01');

2)创建多个分区

给一个表同时增加多个分区,注意多个partition之间没有逗号

alter table dept_partition add 
 partition (day='2018-12-31')
 partition (day='2019-12-31');

 元数据中的分区信息也会进行相应的新增

(3)删除分区

1)删除单个分区

alter table dept_partition drop partition (day='2018-12-31');

2)删除多个分区

注意这里的多个partition之间有逗号

alter table dept_partition drop 
partition (day='2019-12-31'),
partition (day='2023-01-01');

元数据中的分区信息也会进行相应的删除

同样,对应的hdfs分区下的数据也会进行相应的删除

注意:我们这里建立的分区表属于内部表,删除分区时,对应的元数据也会删除,如果建立的分区表属于外部表,删除分区时,对应的元数据不会被删除!!!

create external table if not exists dept_partition_wb
(
    deptno int,--部门编号
    dname  string,-- 部门名称
    loc    string-- 部门位置
) partitioned by (day date)-- 分区字段,当做表中的字段
    row format delimited fields terminated by '\\t'
location '/tables/practices';

select * from dept_partition_wb;-- 外部分区表没有数据

-- 加载数据到外部分区表
load data local inpath '/opt/atguigu/dept_20220401.log'
    into table dept_partition_wb
    partition (day = '2023-02-20');

-- 加载后有数据

-- 再新增一个分区,可以从其他表中查询数据,加载到该外部分区表中
insert overwrite table dept_partition_wb partition (day = '2022-04-02')
select deptno,
       dname,
       loc
from dept_partition
where day = '2023-02-20';

-- 删除外部分区表的某个分区,对应表中的分区数据不存在,但是hdfs上的分区,以及分区下的数据还存在。

drop table dept_partition_wb;

6.修复分区

        Hive将分区表的所有分区信息都保存在了元数据中,只有元数据与HDFS上的分区路径一致时,分区表才能正常读写数据。若用户手动创建/删除分区路径,Hive都是感知不到的,这样就会导致Hive的元数据和HDFS的分区路径不一致。

        再比如,若分区表为外部表,用户执行drop partition命令后,分区元数据会被删除,而HDFS的分区路径不会被删除,同样会导致Hive的元数据和HDFS的分区路径不一致。

(1)add partition

        当我们在hadoop的web端手动创建一个分区,hive并不会感知到新增的分区信息,就会导致Hive的元数据和HDFS的分区路径不一致,需要我们进行分区的修复,保证Hive的元数据和HDFS的分区路径一致。

alter table dept_partition add partition (day='2021-01-09');

修复前:

修复后:

(2)drop partition

        同样地,手动删除一个分区,也需要进行分区的修复。

alter table dept_partition drop partition (day='2021-01-09');

(3)msck(metastore check)

语法:

msck repair table table_name [add/drop/sync partitions];

msck repair table table_name;
-- 等价于
msck repair table table_name add partitions;

msck不需要手动修复指定的分区路径

msck repair table dept_partition add partitions ;
msck repair table dept_partition drop partitions ;
msck repair table dept_partition sync partitions ;

说明:

  • msck repair table table_name add partitions:该命令会增加HDFS路径存在但元数据缺失的分区信息。
  • msck repair table table_name drop partitions:该命令会删除HDFS路径已经删除但元数据仍然存在的分区信息。
  • msck repair table table_name sync partitions:该命令会同步HDFS路径和元数据分区信息,相当于同时执行上述的两个命令。
  • msck repair table table_name:等价于msck repair table table_name add partitions命令。

(二)二级分区表

  • hive一般都是批处理,生产上时间的分区一般是按照天进行分区;
  • 二级分区与普通分区相比,声明两个即可,同样,三级分区声明三个分区,以此类推;
  • 注意:二级分区第一个字段是作为表下面的第一级路径的,第二个字段就是第二级路径;
create table dept_partition2
(
    deptno int,    -- 部门编号
    dname  string, -- 部门名称
    loc    string  -- 部门位置
)
    partitioned by (day string, hour string)
    row format delimited fields terminated by '\\t';

-- 加载数据
load data local inpath '/opt/atguigu/dept_20220401.log' into table dept_partition2
    partition (day = '20220401',hour = '12');

-- 查看分区数据
select * from dept_partition2 where day='20220401' and hour='12';

(三)动态分区

  • 动态分区是指向分区表insert数据时,被写往的分区不由用户指定,而是由每行数据的最后一个字段的值来动态的决定。使用动态分区,可只用一个insert语句将数据写入多个分区。
  • hive中分区不宜太多,分区信息会记录在mysql的分区表中,过多的分区会导致mysql的压力过大,也会影响namenode的内存。
  • 动态分区只需要声明分区字段即可,每条数据的去往哪个分区,是由最后一个字段的值决定的。

1.动态分区相关参数

(1)动态分区功能总开关(默认true,开启)

set hive.exec.dynamic.partition=true;

(2)严格模式和非严格模式

动态分区的模式,默认strict(严格模式),要求必须指定至少一个分区为静态分区,nonstrict(非严格模式)允许所有的分区字段都使用动态分区。大多数情况下是非严格模式。

set hive.exec.dynamic.partition.mode=nonstrict;

(3)一条insert语句可同时创建的最大的分区个数,默认为1000。

set hive.exec.max.dynamic.partitions=1000;

(4)单个Mapper或者Reducer可同时创建的最大的分区个数,默认为100。

set hive.exec.max.dynamic.partitions.pernode=100;

(5)一条insert语句可以创建的最大的文件个数,默认100000。

set hive.exec.max.created.files=100000;

(6)当查询结果为空时且进行动态分区时,是否抛出异常,默认false。

set hive.error.on.empty.partition=false;

案例:

use atguigu;

-- 创建分区表
create table dept_partition_dynamic(
    id int,
    name string
)
partitioned by (loc int)
row format delimited fields terminated by '\\t';

set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode = nonstrict;

insert into table dept_partition_dynamic
partition(loc)
select
    deptno,
    dname,
    loc
from default.dept;

select * from dept_partition_dynamic;

dept_partition_dynamic表中的数据:

进行动态分区后:

二、分桶表

  • 分桶表是将Hive中一张表的数据划分到不同的文件当中;

  • 一张表既可以是分区表,也可以是分桶表,即对每一个分区进行分桶;

  • 不可以对一个字段又分区又分桶,这样没有意义;

  • 声明按照哪个字段进行分桶(即按照哪个字段进行hash分区),字段要选择表中的普通字段,分为几个桶。

1.普通分桶表

drop table stu_bucket;
create table stu_bucket(
    id int,
    name string
)
clustered by (id) into 4 buckets
row format delimited fields terminated by '\\t';

set mapreduce.framework.name=local;
-- 加载数据
set mapreduce.map.memory.mb=4096; --设置map内存
set yarn.scheduler.minimum-allocation-mb=4096; --设置yarn容器最小内存
set mapreduce.map.java.opts=-Xmx3600m; --如果有gc异常可以设置该参数

load data local inpath '/opt/atguigu/student.txt' into table stu_bucket;
select * from stu_bucket;

分桶内容不排序

2.分桶排序表

create table stu_buck_sort(
    id int,
    name string
)
clustered by(id) sorted by(id) into 4 buckets
row format delimited fields terminated by '\\t';
-- 分桶字段和排序字段可以不一致,可以有多个

load data local inpath '/opt/atguigu/student.txt'
into table stu_buck_sort;

分桶内容排序

三、分区表和分桶表的区别

        分区表实际上就是对应一个 HDFS 文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive  中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过 WHERE  子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。

        分区在HDFS上的表现形式是一个目录,分桶则是一个单独的文件。分桶则是指定分桶表的某一列,让该列数据按照哈希取模的方式随机、均匀地分发到各个桶文件中。

以上是关于Hive分区表与分桶表的使用具体说明的主要内容,如果未能解决你的问题,请参考以下文章

打怪升级之小白的大数据之旅(六十六)<Hive旅程第七站:Hive的分区表与分桶表>

打怪升级之小白的大数据之旅(六十六)<Hive旅程第七站:Hive的分区表与分桶表>

Hive的分区表与分桶表&内部表外部表

Hive SQL之分区表与分桶表

大数据之hive:hive分桶表

Hive表的分区与分桶