Hive表---分区表、分桶表以及两者区别

本文介绍了Hive中的分区表和分桶表的概念、创建方法、效率优化以及注意事项。分区表通过目录结构加速查询,而分桶表则通过文件组织提高特定操作效率。
部署运行你感兴趣的模型镜像

一. 分区表:每个分区本质是一个目录

分区表特点/好处: 需要产生分区目录, 查询的时候使用分区字段筛选数据,避免全表扫描从而提升查询效率

效率上注意: 如果分区表,在查询数据的时候没有使用分区字段去筛选数据,效率不变

分区字段名注意: 分区字段名不能和原有字段名重复,因为分区字段名要作为字段拼接到表后

在这里插入图片描述

1. 一级分区

创建分区表:create [external] table [if not exists] 表名(字段名 字段类型 , 字段名 字段类型 , … )partitioned by (分区字段名 分区字段类型)… ;

自动生成分区目录并插入数据: load data [local] inpath ‘文件路径’ into table 分区表名 partition (分区字段名=‘值’);

注意: 如果加local后面文件路径应该是linux本地路径,如果没有加那么就是hdfs文件路径
示例创建一级分区表并加载数据

-- 创建库使用库
create database hive3;
use hive3;
-- 演示分区表
-- 1.一级分区表
-- 建表
create table one_part_order(
    oid string,
    name string,
    price double,
    num int
)partitioned by (year string)
    row format delimited
fields terminated by ' ';
-- 加载数据
-- 先在hdfs的source目录下准备好订单相关数据文件
-- 使用load加载数据到分区表中
load data inpath '/source/order202251.txt' into table one_part_order partition (year=2022);
load data inpath '/source/order2023415.txt' into table one_part_order partition (year='2023');
load data inpath '/source/order202351.txt' into table one_part_order partition (year='2023');
load data inpath '/source/order202352.txt' into table one_part_order partition (year='2023');
-- 验证数据
select * from one_part_order limit 20;

/*分区表特点
去hdfs验证分区表的本质就是分目录存储各个小文件
通过查询发现分区字段最终效果作为一个字段拼接到表最后
*/
-- 分区表的好处:避免全表扫描,提升查询效率
select * from one_part_order where year='2022';
-- 注意: 如果查询的时候条件不是分区字段,效率不会改变
select * from one_part_order where price=20;

2.多级分区

创建分区表: create [external] table [if not exists] 表名(字段名 字段类型 , 字段名 字段类型 , … )partitioned by (一级分区字段名 分区字段类型, 二级分区字段名 分区字段类型 , …) ;

自动生成分区目录并插入数据: load data [local] inpath ‘文件路径’ into table 分区表名 partition (一级分区字段名=‘值’,二级分区字段名=‘值’ , …);

注意: 如果加local后面文件路径应该是linux本地路径,如果没有加那么就是hdfs文件路径

示例创建多级分区表并加载数据

-- 2.多级分区表
-- 创建表
create table multi_part_order(
    oid string,
    name string,
    price float,
    num int
)partitioned by (year string,month string,day string)
    row format delimited
fields terminated by ' ';
-- 加载数据
-- 思考数据文件在哪里?如果想从hdfs加载,怎么操作?上传到hdfs指定位置
load data inpath '/source/order202251.txt' into table multi_part_order partition (year=2022,month=05,day=01);
load data inpath '/source/order202351.txt' into table multi_part_order partition (year=2023,month=05,day=01);
load data inpath '/source/order202352.txt' into table multi_part_order partition (year=2023,month=05,day=02);
load data inpath '/source/order2023415.txt' into table multi_part_order partition (year=2023,month=04,day=15);
-- 验证数据
select * from multi_part_order;

-- 分区表的好处:避免全表扫描,提升查询效率
-- 需求: 统计2023年商品总销售额
select sum(price*num) from multi_part_order where year='2023'; -- 提升效率
-- 需求: 统计2023年5月份商品总销售额
select sum(price*num) from multi_part_order where year='2023'and month='5'; -- 提升效率
-- 需求: 统计2023年5月1日的商品总销售额
select sum(price*num) from multi_part_order where year='2023'and month='5' and day='1'; -- 提升效率

3.分区操作

添加分区: alter table 分区表名 add partition (分区字段名=‘值’ , …);

删除分区: alter table 分区表名 drop partition (分区字段名=‘值’ , …);

修改分区名: alter table 分区表名 partition (分区字段名=‘旧值’ , …) rename to partition (分区字段名=‘新值’ , …);

查看所有分区: show partitons 分区表名;

同步/修复分区: msck repair table 分区表名;

-- 分区操作
-- 注意: 先确定有一级分区和多级分区表,如果没有先创建再做分区操作
select * from one_part_order limit 20;
select * from multi_part_order limit 20;

-- 添加分区(本质在hdfs上创建分区目录)
alter table one_part_order add partition (year=2024);
alter table multi_part_order add partition (year=2024,month=5,day=1);

-- 修改分区(本质在hdfs上修改分区目录名)
alter table one_part_order partition (year=2024) rename to partition (year=2030);
alter table multi_part_order  partition (year=2024,month=5,day=1) rename to partition (year=2030,month=6,day=10);

-- 查看所有分区
show partitions one_part_order;
show partitions multi_part_order;

-- 删除分区
alter table multi_part_order drop partition (year=2030,month=6,day=10);
alter table multi_part_order drop partition (year=2023,month=5,day=2);
alter table multi_part_order drop partition (year=2023,month=5);
alter table multi_part_order drop partition (year=2023,month=4);
alter table multi_part_order drop partition (year=2022);

-- 如果在hdfs上创建符合分区目录格式的文件夹,可以使用msck repair修复
-- 举例:手动创建一个year=2033目录
msck repair table one_part_order;
msck repair table multi_part_order;
-- 修复后再次查看所有分区
show partitions one_part_order;
show partitions multi_part_order;

hadoop_hive文档

hive文档: https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties
hdfs文档: https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
yarn文档: https://hadoop.apache.org/docs/stable/hadoop-yarn/hadoop-yarn-common/yarn-default.xml
mr文档: https://hadoop.apache.org/docs/stable/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml

二. 分桶表:每个分桶本质是一个文件

分桶表特点/好处: 需要产生分桶文件, 查询的时候特定操作上提升效率(过滤,join,分组 以及 抽样)

效率上注意: 如果分桶表,在查询数据的时候没有使用分桶字段去筛选数据,效率不变

分桶字段名注意: 分桶字段名必须是原有字段名, 因为分桶需要根据对应字段值取余数把余数相同的数据放到同一个分桶

在这里插入图片描述

1. 重要参数

-- 默认开启,hive2.x版本已经被移除
set hive.enforce.bucketing; -- 查看未定义因为已经被移除
set hive.enforce.bucketing=true; -- 修改

-- 查看reduce数量
-- 参数优先级: set方式 > hive文档 > hadoop文档
set mapreduce.job.reduces; -- 查看默认-1,代表自动根据桶数量匹配reduce数量
set mapreduce.job.reduces=3; -- 设置参数

2. 基础分桶表

创建基础分桶表:
create [external] table [if not exists] 表名(
字段名 字段类型
)
clustered by (分桶字段名)
into 桶数量 buckets ;

示例创建基础分桶表并加载数据

-- 1.创建基础分桶表,要求分3个桶
create table course_base (
    cid int,
    cname string,
    sname string
)
clustered by(cid) into 3 buckets
row format delimited fields terminated by '\t';

-- 2.load方式加载数据
-- 前提: 已经上传course.txt文件到hdfs的/source目录下
load data inpath '/source/course.txt' into table course_base;

-- 3.查询数据,观察结果
select * from course_base;

3. 分桶表排序

创建基础分桶表,然后桶内排序:
create [external] table [if not exists] 表名(
字段名 字段类型
)
clustered by (分桶字段名)
sorted by(排序字段名 asc|desc) # 注意:asc升序(默认) desc降序
into 桶数量 buckets ;

示例创建分桶排序表并加载数据

-- 1.创建基础分桶表,要求分3个桶,桶内根据cid降序
create table course_sort (
    cid int,
    cname string,
    sname string
)
clustered by(cid) sorted by (cid desc) into 3 buckets
row format delimited fields terminated by '\t';

-- 2.加载数据
-- 还是使用/source/course.txt数据文件
load data inpath '/source/course.txt' into table course_sort;

-- 3.查询数据,观察结果
select * from course_sort;

分桶原理

如果是数值类型分桶字段: 直接使用数值对桶数量取模
如果是字符串类型分桶字段: 底层会使用hash算法计算出一个数字然后再对桶数量取模

Hash: Hash是一种数据加密算法,其原理我们不去详细讨论,我们只需要知道其主要特征:同样的值被Hash加密后的结果是一致的
举例: 字符串“binzi”被Hash后的结果是93742710(仅作为示意),那么无论计算多少次,字符串“binzi”的结果都会是93742710。
计算余数: hash(‘binzi’)%3==0
注意: 同样的数据得到的结果一致,如’binzi’ hash取模结果是0,无论计算多少次,它的取模结果都是0

[重点]分区表和分桶表的区别

分区表
创建表的时候使用关键字: partition by (分区字段名 分区字段类型)

分区字段名注意事项: 是一个新的字段,需要指定类型,且不能和其他字段重名

分区表好处: 使用分区字段作为条件的时候,底层直接找到对应的分区目录,能够避免全表扫描,提升查询效率

分区表最直接的效果: 在hfds表目录下,分成多个分区目录(year=xxxx,month=xx,day=xx)

不建议直接上传文件在hdfs表根路径下: 分区不能识别对应文件中数据,因为分区表会找分区目录下的数据文件

使用load方式加载hdfs中文件: 本质是移动文件到对应分区目录下

分桶表
创建表的时候使用关键字: clustered by (分桶字段名) into 桶数量 buckets

分桶字段名注意事项: 是指定一个已存在的字段,不需要指定类型

分桶表好处: 使用分桶字段做抽样等特定操作的时候,也能提升性能效率

分桶表最直接的效果: 在hdfs表目录或者分区目录下,分成多个分桶文件(000000_0,000001_0,000002_0…)

不建议直接上传文件在hdfs表根路径下: 分桶表可以识别对应文件中数据,但是并没有分桶效果,也是不建议的

使用load方式加载hdfs中文件: 本质是复制数据到各个分桶文件中

您可能感兴趣的与本文相关的镜像

Yolo-v8.3

Yolo-v8.3

Yolo

YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

<think>嗯,用户现在想了解Hive分区表结合使用的实现方式最佳实践。我之前已经回答过他们关于LOAD DATA的问题,现在他们进一步深入,想了解两者的结合使用。需要参考用户提供的引用内容,特别是引用[3]中的示例,还有引用[5]中的动态静态区的例子。首先,分区表的基本概念需要明确。分区表是按目录划数据,比如按日期区,而则是将数据按哈希成小文件。结合使用时,通常是先区再,这样可以进一步细化数据存储,提高查询效率。然后,用户需要具体的实现方法,比如如何创建联合使用的结构。引用[3]中的示例已经展示了的结合,应该用那个例子作为基础。同时,动态静态区的区别也需要说明,引用[5]提到了动态区的操作步骤,可以整合进去。 接下来,最佳实践部需要包括区键键的选择原则。比如区键选择低基数的字段,键选择高基数的字段,这样能保证数据布均匀。同时,数的计算预排序的优化也很重要,需要结合之前的回答中的数学公式性能对比数据。还要考虑数据加载的问题,比如使用INSERT OVERWRITE来动态加载数据,这时候需要设置hive.exec.dynamic.partition.mode为nonstrict,允许动态区。同时,的正确性验证方法,比如检查每个区的数据量是否均匀,可以引用用户之前提到的ANALYZE TABLE命令。示例部需要详细展示建语句数据插入步骤,特别是动态的结合使用。可能需要给出一个具体的场景,比如按日期区,按用户ID,这样在查询时可以利用区裁剪的优化效果。 最后,注意事项部要提醒用户数的调整、JOIN优化以及压缩格式的选择,比如ORCSNAPPY压缩,这些在之前的引用中都有提到,特别是引用[4]中关于Oracle区的类比,可以强调区的通用性重要性。 需要确保回答结构清晰,步骤说明,结合代码示例实际场景,同时引用相关的引用来源。可能还需要生成相关问题,比如如何优化联合使用时的查询性能,或者如何处理数据倾斜的问题,这些在之前的回答中也有涉及,可以自然延伸出来。</think>### Hive分区表结合使用详解 --- #### 一、结合使用原理 1. **层级划逻辑** - **分区表**:按字段值(如日期、地区)划目录层级,实现**粗粒度数据管理** - ****:在区基础上,通过哈希算法将数据细为多个文件,实现**细粒度优化** - 组合效果:`区目录 > 文件`,形成二级数据划结构[^3] 2. **性能优势** $$ \text{查询效率} = \frac{\text{全扫描时间}}{\text{区裁剪因子} \times \text{过滤因子}} $$ 例如:100GB数据按日期区后缩小至5GB/区,再32个文件,单文件仅156MB --- #### 二、实现方法 ##### 1. 定义语法 ```sql CREATE TABLE user_behavior ( user_id BIGINT, event_time STRING, action_type STRING ) PARTITIONED BY (dt STRING) -- 按天区 CLUSTERED BY (user_id) -- 按用户 SORTED BY (event_time) -- 按时间排序 INTO 64 BUCKETS -- 数量 STORED AS ORC TBLPROPERTIES ("orc.compress"="SNAPPY"); ``` - **区键选择**:低基数字段(如日期、地区),避免产生过多空目录[^5] - **键选择**:高基数字段(如用户ID、订单号),保证数据均匀布[^1] ##### 2. 数据加载示例 ```sql -- 启用动态区配置 SET hive.exec.dynamic.partition=true; SET hive.exec.dynamic.partition.mode=nonstrict; -- 从原始加载数据 INSERT OVERWRITE TABLE user_behavior PARTITION (dt) -- 动态区字段 SELECT user_id, event_time, action_type, DATE_FORMAT(event_time, 'yyyy-MM-dd') AS dt -- 自动生成区值 FROM raw_logs CLUSTER BY user_id; -- 触发操作 ``` - **动态区**:自动根据`dt`字段值创建区目录 - **保证**:`CLUSTER BY`确保数据按哈希规则布到中[^2] --- #### 三、最佳实践 ##### 1. 联合优化策略 | 优化维度 | 分区表策略 | 策略 | |---------------|-----------------------------|-----------------------------| | 存储粒度 | 按天/月区 | 按用户ID64 | | 查询加速 | WHERE dt='2023-08-01' | JOIN ON user_id | | 文件管理 | 自动清理旧区 | 合并小文件 | ##### 2. 参数调优建议 ```sql -- 区优化 SET hive.optimize.sort.dynamic.partition=true; -- 动态区排序优化 -- 优化 SET hive.enforce.bucketing=true; -- 强制检查 SET hive.optimize.bucketmapjoin=true; -- 启用MapJoin ``` ##### 3. 数据验证方法 ```sql -- 检查区数据布 SHOW PARTITIONS user_behavior; -- 验证均匀性(方差应接近0) SELECT dt, VARIANCE(bucket_size) FROM ( SELECT dt, COUNT(*) AS bucket_size FROM user_behavior TABLESAMPLE(BUCKET 1 OUT OF 64 ON user_id) GROUP BY dt ) t GROUP BY dt; ``` --- #### 四、典型应用场景 1. **时间序列析** ```sql -- 析某日用户行为布 SELECT action_type, COUNT(*) FROM user_behavior WHERE dt='2023-08-01' -- 触发区裁剪 GROUP BY action_type; ``` 2. **用户画像JOIN** ```sql -- 与用户维度关联(键一致) SELECT u.gender, AVG(b.event_count) FROM user_profile u JOIN ( SELECT user_id, COUNT(*) AS event_count FROM user_behavior WHERE dt BETWEEN '2023-07-01' AND '2023-07-31' GROUP BY user_id ) b ON u.user_id = b.user_id; -- 触发Bucket Map Join[^1] ``` --- #### 五、注意事项 1. **数调整** 数一旦确定无法直接修改,需重建: ```sql CREATE TABLE new_table ... INTO 128 BUCKETS; INSERT INTO new_table SELECT * FROM old_table; ``` 2. **数据倾斜处理** 若发现不均匀,可添加随机盐值: ```sql CLUSTER BY CONCAT(user_id, '_', FLOOR(RAND()*10)) ``` 3. **存储格式选择** 优先使用ORC格式,其内置索引可加速查询[^3] ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值