hive分区分桶
1、分区
如果一个表中数据很多,我们查询时就很慢,耗费大量时间,如果要查询其中部分数据该怎么办呢,这时我们引入分区的概念。
Hive 中的分区表分为两种:静态分区和动态分区。
1.1、静态分区
可以根据 PARTITIONED BY 创建分区表。
一个表可以拥有一个或者多个分区,每个分区以文件夹的形式单独存在表文件夹的目录下。
- 一个分区:表目录下只有一级目录。
- 多个分区:表目录下是多级目录。
分区列是虚拟列,它们不是数据本身的一部分,而是在加载时派生的。
1.1.1、一个分区
-- 建表
create table order_table_s
(
order_id int, -- 订单id
product_name string, -- 产品名称
price int -- 产品价格
)
partitioned by (deal_day string) -- 交易日期YYYYMM
row format delimited
fields terminated by "\t";
-- 查看表结构
hive> desc order_table_s;
OK
order_id int
product_name string
price int
deal_day string
# Partition Information
# col_name data_type comment
deal_day string
-- 源数据
-- order-201901.txt
1 cellphone 2000
2 tv 3000
3 sofa 8000
4 cabinet 5000
5 bicycle 1000
6 truck 20000
-- order-201902.txt
1 apple 10
2 banana 8
3 milk 70
4 liquor 150
-- 导入数据
load data local inpath '/root/data/order-201901.txt' overwrite into table order_table_s partition(deal_day='201901');
load data local inpath '/root/data/order-201902.txt' overwrite into table order_table_s partition(deal_day='201902');
-- 查看表
hive> select * from order_table_s;
1 cellphone 2000 201901
2 tv 3000 201901
3 sofa 8000 201901
4 cabinet 5000 201901
5 bicycle 1000 201901
6 truck 20000 201901
1 apple 10 201902
2 banana 8 201902
3 milk 70 201902
4 liquor 150 201902
-- 查看201902的数据
hive> select * from order_table_s where deal_day='201902';
1 apple 10 201902
2 banana 8 201902
3 milk 70 201902
4 liquor 150 201902
-- 查看hdfs目录
[root@zgg data]# hadoop fs -ls /user/hive/warehouse/order_table_s
Found 2 items
drwxr-xr-x - root supergroup 0 2021-01-08 16:05 /user/hive/warehouse/order_table_s/deal_day=201901
drwxr-xr-x - root supergroup 0 2021-01-08 16:27 /user/hive/warehouse/order_table_s/deal_day=201902
[root@zgg data]# hadoop fs -ls /user/hive/warehouse/order_table_s/deal_day=201901
Found 1 items
-rw-r--r-- 1 root supergroup 56 2021-01-08 18:23 /user/hive/warehouse/order_table_s/deal_day=201901/000000_0
[root@zgg data]# hadoop fs -ls /user/hive/warehouse/order_table_s/deal_day=201901
Found 1 items
-rw-r--r-- 1 root supergroup 83 2021-01-08 16:05 /user/hive/warehouse/order_table_s/deal_day=201901/order-201901.txt
-- 查看mysql中的元数据
mysql> select * from PARTITION_KEY_VALS;
+---------+--------------+-------------+
| PART_ID | PART_KEY_VAL | INTEGER_IDX |
+---------+--------------+-------------+
| 16 | 201901 | 0 |
| 21 | 201902 | 0 |
+---------+--------------+-------------+
-- 删除分区201902
-- ALTER TABLE table_name DROP partition_spec, partition_spec,...
hive> alter table order_table_s drop partition(deal_day='201902');
-- 删除后,查看表
hive> select * from order_table_s;
1 cellphone 2000 201901
2 tv 3000 201901
3 sofa 8000 201901
4 cabinet 5000 201901
5 bicycle 1000 201901
6 truck 20000 201901
-- 删除后,查看hdfs目录
[root@zgg data]# hadoop fs -ls /user/hive/warehouse/order_table_s
Found 1 items
drwxr-xr-x - root supergroup 0 2021-01-08 16:05 /user/hive/warehouse/order_table_s/deal_day=201901
-- 删除后,查看mysql中的元数据
mysql> select * from PARTITION_KEY_VALS;
+---------+--------------+-------------+
| PART_ID | PART_KEY_VAL | INTEGER_IDX |
+---------+--------------+-------------+
| 16 | 201901 | 0 |
+---------+--------------+-------------+
-- 删除后,数据和元数据都被删除了
-- ---------------------------------------------------
-- 重新添加分区201902
-- 这里的location是这个分区的数据存放的位置,默认是`/user/hive/warehouse/order_table_s`
alter table order_table_s add partition(deal_day='201902') location '/in/order';
-- 把order-201902.txt移动到'/in/order'目录下
-- 所以导入数据,也可以直接复制到对应的目录下。
[root@zgg data]# hadoop fs -mv /in/order-201902.txt /in/order
-- 查看201902的数据
hive> select * from order_table_s where deal_day='201902';
1 apple 10 201902
2 banana 8 201902
3 milk 70 201902
4 liquor 150 201902
-- hive中查询分区
hive> show partitions order_table_s;
deal_day=201901
deal_day=201902
-- 如果直接将数据复制到分区目录下,select没有数据的话,可以执行`msck repair table order_table_s` 重新同步hdfs上的分区信息。
1.1.2、多个分区
-- 建表:两个分区
create table order_table_d
(
order_id int, -- 订单id
product_name string, -- 产品名称
price int -- 产品价格
)
partitioned by (deal_day string,category string) -- 交易日期YYYYMM,产品类别
row format delimited
fields terminated by "\t";
-- 查看表结构
hive> desc order_table_d;
OK
order_id int
product_name string
price int
deal_day string
category string
# Partition Information
# col_name data_type comment
deal_day string
category string
-- 源数据
-- order-201901-electronicproducts.txt
1 cellphone 2000
2 tv 3000
-- order-201901-car.txt
1 bicycle 1000
2 truck 20000
-- order-201902-fruit.txt
1 apple 10
2 banana 8
-- order-201902-drinks.txt
1 milk 70
2 liquor 150
-- 导入数据
load data local inpath '/root/data/order-201901-electronicproducts.txt' overwrite into table order_table_d partition(deal_day='201901',category='electronicproducts');
load data local inpath '/root/data/order-201901-car.txt' overwrite into table order_table_d partition(deal_day='201901',category='car');
load data local inpath '/root/data/order-201902-fruit.txt' overwrite into table order_table_d partition(deal_day='201902',category='fruit');
load data local inpath '/root/data/order-201902-drinks.txt' overwrite into table order_table_d partition(deal_day='201902',category='drinks');
-- 查看
hive> select * from order_table_d;
OK
1 bicycle 1000 201901 car
2 truck 20000 201901 car
1 cellphone 2000 201901 electronicproducts
2 tv 3000 201901 electronicproducts
1 milk 70 201902 drinks
2 liquor 150 201902 drinks
1 apple 10 201902 fruit
2 banana 8 201902 fruit
hive> show partitions order_table_d;
OK
deal_day=201901/category=car
deal_day=201901/category=electronicproducts
deal_day=201902/category=drinks
deal_day=201902/category=fruit
-- 查看hdfs目录
[root@zgg data]# hadoop fs -ls /user/hive/warehouse/order_table_d
Found 2 items
drwxr-xr-x - root supergroup 0 2021-01-08 17:00 /user/hive/warehouse/order_table_d/deal_day=201901
drwxr-xr-x - root supergroup 0 2021-01-08 17:00 /user/hive/warehouse/order_table_d/deal_day=201902
[root@zgg data]# hadoop fs -ls /user/hive/warehouse/order_table_d/deal_day=201901
Found 2 items
drwxr-xr-x - root supergroup 0 2021-01-08 17:00 /user/hive/warehouse/order_table_d/deal_day=201901/category=car
drwxr-xr-x - root supergroup 0 2021-01-08 17:00 /user/hive/warehouse/order_table_d/deal_day=201901/category=electronicproducts
-- 查看mysql中的元数据
mysql> select * from PARTITION_KEY_VALS;
+---------+--------------------+-------------+
| PART_ID | PART_KEY_VAL | INTEGER_IDX |
+---------+--------------------+-------------+
| 23 | 201901 | 0 |
| 23 | electronicproducts | 1 |
| 24 | 201901 | 0 |
| 24 | car | 1 |
| 25 | 201902 | 0 |
| 25 | fruit | 1 |
| 26 | 201902 | 0 |
| 26 | drinks | 1 |
+---------+--------------------+-------------+
-- 删除分区deal_day=201902/category=fruit
hive> alter table order_table_d drop partition(deal_day='201902',category='fruit');
-- 删除后,查看表分区
hive> show partitions order_table_d;
OK
deal_day=201901/category=car
deal_day=201901/category=electronicproducts
deal_day=201902/category=drinks
-- 删除后,查看hdfs目录
[root@zgg data]# hadoop fs -ls /user/hive/warehouse/order_table_d/deal_day=201902
Found 1 items
drwxr-xr-x - root supergroup 0 2021-01-08 17:00 /user/hive/warehouse/order_table_d/deal_day=201902/category=drinks
-- 删除后,查看mysql中的元数据
mysql> select * from PARTITION_KEY_VALS;
+---------+--------------------+-------------+
| PART_ID | PART_KEY_VAL | INTEGER_IDX |
+---------+--------------------+-------------+
| 23 | 201901 | 0 |
| 23 | electronicproducts | 1 |
| 24 | 201901 | 0 |
| 24 | car | 1 |
| 26 | 201902 | 0 |
| 26 | drinks | 1 |
+---------+--------------------+-------------+
-- 重新添加分区deal_day=201902/category=fruit
hive> alter table order_table_d add partition(deal_day='201902',category='fruit');
-- 重新导入
hive> load data local inpath '/root/data/order-201902-drinks.txt' overwrite into table order_table_d partition(deal_day='201902',category='drinks');
-- 查看
hive> select * from order_table_d;
1 bicycle 1000 201901 car
2 truck 20000 201901 car
1 cellphone 2000 201901 electronicproducts
2 tv 3000 201901 electronicproducts
1 milk 70 201902 drinks
2 liquor 150 201902 drinks
hive> show partitions order_table_d;
deal_day=201901/category=car
deal_day=201901/category=electronicproducts
deal_day=201902/category=drinks
deal_day=201902/category=fruit
-- 导入数据到分区表,还可以使用 insert
-- 将order_table_d的201901分区中的数据插入到order_table_s的201901分区中
-- 查看order_table_s数据
hive> select * from order_table_s;
1 apple 10 201902
2 banana 8 201902
3 milk 70 201902
4 liquor 150 201902
hive> insert into table order_table_s partition(deal_day='201901') select order_id,product_name,price from order_table_d where deal_day='201901';
-- 查看结果
hive> select * from order_table_s where deal_day='201901';
1 bicycle 1000 201901
2 truck 20000 201901
1 cellphone 2000 201901
2 tv 3000 201901
1.2、动态分区
上面展示了如何使用 insert 插入到分区表,如果再插入分区 '201902' 数据,需要再写一条 insert 语句。
而动态分区可以直接使用一条 insert 语句完成。
下面利用动态分区进行演示。
演示前先进行设置:
hive 中默认是静态分区,想要使用动态分区,需要设置如下参数,可以使用临时设置,也可以写在配置文件(hive-site.xml)里,永久生效。临时配置如下:
//开启动态分区 默认为false,不开启
set hive.exec.dynamic.partition=true;
//指定动态分区模式,默认为strict,即必须指定至少一个分区为静态分区,
//nonstrict模式表示允许所有的分区字段都可以使用动态分区
set hive.exec.dynamic.partition.mode=nonstrict;
-- 创建动态分区表
create table order_table_dy
(
order_id int, -- 订单id
product_name string, -- 产品名称
price int -- 产品价格
)
partitioned by (deal_day string) -- 交易日期YYYYMM,产品类别
row format delimited
fields terminated by "\t";
hive> select * from order_table_s;
1 bicycle 1000 201901
2 truck 20000 201901
1 cellphone 2000 201901
2 tv 3000 201901
1 apple 10 201902
2 banana 8 201902
3 milk 70 201902
4 liquor 150 201902
-- 将order_table_s表里的两个分区的数据插入到order_table_dy表
hive> insert into table order_table_dy(deal_day) select order_id,product_name,price,deal_day from order_table_s;
-- 查看结果
hive> select * from order_table_dy where deal_day=201901;
OK
1 bicycle 1000 201901
2 truck 20000 201901
1 cellphone 2000 201901
2 tv 3000 201901
hive> select * from order_table_dy where deal_day=201902;
OK
1 apple 10 201902
2 banana 8 201902
3 milk 70 201902
4 liquor 150 201902
hive> show partitions order_table_dy;
OK
deal_day=201901
deal_day=201902
静态分区(SP)列:在涉及多个分区列的 DML/DDL 中,这些列的值在编译时已知(由用户给出)。
动态分区(DP)列:在执行时才知道其值的列。
DP 列的指定方式与 SP 列的指定方式相同:在 partition 子句中。唯一的区别是 DP 列没有值,而 SP 列有。在 partition 子句中,我们需要指定所有分区列,即使它们都是 DP 列。
在 INSERT ... SELECT ...
查询时,动态分区列必须在 SELECT 语句中的最后一个列中指定,且顺序与它们在 PARTITION() 子句中出现的顺序相同。
-- 正确
INSERT OVERWRITE TABLE T PARTITION (ds='2010-03-03', hr)
SELECT key, value, /*ds,*/ hr FROM srcpart WHERE ds is not null and hr>10;
-- 错误
INSERT OVERWRITE TABLE T PARTITION (ds, hr = 11)
SELECT key, value, ds/*, hr*/ FROM srcpart WHERE ds is not null and hr=11;
2、分桶
通过计算表的某些列的哈希值,分区中的数据再被划分到桶中。
例如,page_views 表根据 userid 分桶,userid 是 page_view 表的列之一,而不是分区列。
将表或分区组织成桶有以下几个目的:
(1)抽样更高效,因为在处理大规模的数据集时,在开发、测试阶段将所有的数据全部处理一遍可能不太现实,这时抽样就必不可少。
抽样:
SELECT * FROM table_name TABLESAMPLE(n PERCENT);
抽样出n%的数据,会全表扫描。
有了桶之后呢?
如果在 TABLESAMPLE 子句中指定的列与 CLUSTERED BY 子句中的列相匹配,则 TABLESAMPLE 只扫描表中要求的哈希分区【就是具体的桶】
SELECT * FROM film TABLESAMPLE(BUCKET x OUTOF y)
如果表是用 `CLUSTERED BY id INTO 32 BUCKETS` 创建的。
TABLESAMPLE(BUCKET 3 OUT OF 16 ON id):
将挑选出第 3 和第 19 个聚类,因为每个桶将由 (32/16)=2 个聚类组成。
【每个桶有2个聚类,一共64个聚类,取出第 3 和第 19 个聚类】
TABLESAMPLE(BUCKET 3 OUT OF 64 ON id):
将挑选出第 3 个聚类的一半,因为每个桶将由 (32/64)=1/2 个聚类组成
(2)更好的查询处理效率。
大表在JOIN的时候,效率低下。如果对两个表先分别按id分桶,那么相同id都会归入一个桶。
那么此时再进行JOIN的时候是按照桶来JOIN的,那么大大减少了JOIN的数量。
在建立桶之前,需要设置 set hive.enforce.bucketing=true;
,使得 hive 能识别桶。【仅版本 0.x 和 1.x,对于2.x版本不再需要】
hive> select * from order_table_s;
OK
1 bicycle 1000 201901
2 truck 20000 201901
1 cellphone 2000 201901
2 tv 3000 201901
1 apple 10 201902
2 banana 8 201902
3 milk 70 201902
4 liquor 150 201902
-- 创建分桶
create table order_table_buckets
(
order_id int, -- 订单id
product_name string, -- 产品名称
price int -- 产品价格
)
partitioned by (deal_day string) -- 交易日期YYYYMM,产品类别
clustered by (order_id) into 4 buckets
row format delimited
fields terminated by "\t";
-- 导入数据:
hive> insert into table order_table_buckets partition(deal_day) select order_id,product_name,price,deal_day from order_table_s where order_id=1;
-- 查看表
hive> select * from order_table_buckets;
OK
1 cellphone 2000 201901
1 bicycle 1000 201901
1 apple 10 201902
-- 查看hdfs中的目录
[root@zgg ~]# hadoop fs -ls /user/hive/warehouse/order_table_buckets
Found 2 items
drwxr-xr-x - root supergroup 0 2021-01-08 18:49 /user/hive/warehouse/order_table_buckets/deal_day=201901
drwxr-xr-x - root supergroup 0 2021-01-08 18:49 /user/hive/warehouse/order_table_buckets/deal_day=201902
[root@zgg ~]# hadoop fs -ls /user/hive/warehouse/order_table_buckets/deal_day=201901
Found 4 items
-rw-r--r-- 1 root supergroup 0 2021-01-08 18:49 /user/hive/warehouse/order_table_buckets/deal_day=201901/000000_0
-rw-r--r-- 1 root supergroup 32 2021-01-08 18:49 /user/hive/warehouse/order_table_buckets/deal_day=201901/000001_0
-rw-r--r-- 1 root supergroup 0 2021-01-08 18:49 /user/hive/warehouse/order_table_buckets/deal_day=201901/000002_0
-rw-r--r-- 1 root supergroup 0 2021-01-08 18:49 /user/hive/warehouse/order_table_buckets/deal_day=201901/000003_0
参考:
https://blog.51cto.com/10814168/2135046
hive分区分桶的更多相关文章
- Hive 实战(2)--hive分区分桶实战
前言: 互联网应用, 当Mysql单机遇到性能瓶颈时, 往往采用的优化策略是分库分表. 由于互联网应用普遍的弱事务性, 这种优化效果非常的显著.而Hive作为数据仓库, 当数据量达到一定数量时, 查询 ...
- 大数据入门第十一天——hive详解(二)基本操作与分区分桶
一.基本操作 1.DDL 官网的DDL语法教程:点击查看 建表语句 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_name data ...
- 二 Hive分桶
二.Hive分桶 1.创建分桶表 create table t_buck (id string ,name string) clustered by (id) //根据id分桶 sorted by ( ...
- Hive分区和桶的概念
Hive 已是目前业界最为通用.廉价的构建大数据时代数据仓库的解决方案了,虽然也有 Impala 等后起之秀,但目前从功能.稳定性等方面来说,Hive 的地位尚不可撼动. 其实这篇博文主要是想聊聊 S ...
- Hadoop Hive概念学习系列之hive里的桶(十一)
不多说,直接上干货! Hive还可以把表或分区,组织成桶.将表或分区组织成桶有以下几个目的: 第一个目的是为看取样更高效,因为在处理大规模的数据集时,在开发.测试阶段将所有的数据全部处理一遍可能不太 ...
- 游戏全区全服和分区分服 QQ斗地主的设计
游戏全区全服和分区分服 QQ斗地主的设计 https://cloud.tencent.com/community/article/164816001481011910?fromSource=gwzc ...
- FreeSql (三十一)分区分表
分区 分区就是把一个数据表的文件和索引分散存储在不同的物理文件中.把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上,数据库不同实现方式有所不同. 与分表不同,一张大表进行 ...
- SqlServer数据库分区分表实例分享(有详细代码和解释)
数据库单表数据量太大可能会导致数据库的查询速度大大下降(感觉都是千万级以上的数据表了),可以采取分区分表将大表分为小表解决(当然这只是其中一种方法),比如数据按月.按年分表,最后可以使用视图将小表重新 ...
- 一文搞懂│mysql 中的备份恢复、分区分表、主从复制、读写分离
目录 mysql 的备份和恢复 mysql 的分区分表 mysql 的主从复制读写分离 mysql 的备份和恢复 创建备份管理员 创建备份管理员,并授予管理员相应的权限 备份所需权限:select,r ...
随机推荐
- Java复习整理 day01
练习代码: 1 //这条语句说明这个Java文件在demo的包下 2 package demo1; 3 /** 4 * 5 * @author 王兴平 6 * 这个是第一个hello world 案例 ...
- PIE模型
首先,我们需要明确程序的Bug有如下的定义: 1. Fault/Defect 静态的,存在于软件中的缺陷.例如:一段有缺失或者错误的代码. 2. Error 运行时一种不正确的中间状态. 3. Fai ...
- 从微信小程序到鸿蒙js开发【05】——tabs组件&每日新闻
目录: 1.tabs, tab-bar, tab-content 2.tabs的事件处理 3.tabs实现的每日新闻 1.tabs, tab-bar, tab-content 上章说到,鸿蒙的list ...
- BZOJ3238 [Ahoi2013]差异 【SAM or SA】
BZOJ3238 [Ahoi2013]差异 给定一个串,问其任意两个后缀的最长公共前缀长度的和 1.又是后缀,又是\(lcp\),很显然直接拿\(SA\)的\(height\)数组搞就好了,配合一下单 ...
- Codeforces Round #649 (Div. 2) B. Most socially-distanced subsequence
题目链接:https://codeforces.com/contest/1364/problem/B 题意 给出大小为 $n$ 的一个排列 $p$,找出子序列 $s$,使得 $|s_1-s_2|+|s ...
- Consonant Fencity Gym - 101612C 暴力二进制枚举 Intelligence in Perpendicularia Gym - 101612I 思维
题意1: 给你一个由小写字母构成的字符串s,你可以其中某些字符变成大写字母.如果s中有字母a,你如果想把a变成大写,那s字符串中的每一个a都要变成A 最后你需要要出来所有的字符对,s[i]和s[i-1 ...
- HihoCoder-1870 Jin Yong’s Wukong Ranking List(并查集)
我发现大佬好像都是用拓扑排序写的(本菜鸡不会拓扑哭唧唧 说一下并查集的做法吧... 就是找两人右边的(辣鸡的那个人)那个是否比左边厉害,厉害的话就矛盾. 如果他俩没比较过就把厉害的并到辣鸡的. (辣鸡 ...
- Go语言中时间轮的实现
最近在工作中有一个需求,简单来说就是在短时间内会创建上百万个定时任务,创建的时候会将对应的金额相加,防止超售,需要过半个小时再去核对数据,如果数据对不上就需要将加上的金额再减回去. 这个需求如果用Go ...
- C++ part6.5
1.虚函数表建立和虚函数表指针初始化 虚拟函数表是在编译期就建立了,各个虚拟函数这时被组织成了一个虚拟函数的入口地址的数组.而虚函数表指针是在运行期,也就是构造函数被调用时进行初始化的,这是实现多态的 ...
- 操作系统 part5
1.线程安全 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据污染. 线程不安全就 ...