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分区分桶的更多相关文章

  1. Hive 实战(2)--hive分区分桶实战

    前言: 互联网应用, 当Mysql单机遇到性能瓶颈时, 往往采用的优化策略是分库分表. 由于互联网应用普遍的弱事务性, 这种优化效果非常的显著.而Hive作为数据仓库, 当数据量达到一定数量时, 查询 ...

  2. 大数据入门第十一天——hive详解(二)基本操作与分区分桶

    一.基本操作 1.DDL 官网的DDL语法教程:点击查看 建表语句 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_name data ...

  3. 二 Hive分桶

    二.Hive分桶 1.创建分桶表 create table t_buck (id string ,name string) clustered by (id) //根据id分桶 sorted by ( ...

  4. Hive分区和桶的概念

    Hive 已是目前业界最为通用.廉价的构建大数据时代数据仓库的解决方案了,虽然也有 Impala 等后起之秀,但目前从功能.稳定性等方面来说,Hive 的地位尚不可撼动. 其实这篇博文主要是想聊聊 S ...

  5. Hadoop Hive概念学习系列之hive里的桶(十一)

    不多说,直接上干货!  Hive还可以把表或分区,组织成桶.将表或分区组织成桶有以下几个目的: 第一个目的是为看取样更高效,因为在处理大规模的数据集时,在开发.测试阶段将所有的数据全部处理一遍可能不太 ...

  6. 游戏全区全服和分区分服 QQ斗地主的设计

    游戏全区全服和分区分服  QQ斗地主的设计 https://cloud.tencent.com/community/article/164816001481011910?fromSource=gwzc ...

  7. FreeSql (三十一)分区分表

    分区 分区就是把一个数据表的文件和索引分散存储在不同的物理文件中.把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上,数据库不同实现方式有所不同. 与分表不同,一张大表进行 ...

  8. SqlServer数据库分区分表实例分享(有详细代码和解释)

    数据库单表数据量太大可能会导致数据库的查询速度大大下降(感觉都是千万级以上的数据表了),可以采取分区分表将大表分为小表解决(当然这只是其中一种方法),比如数据按月.按年分表,最后可以使用视图将小表重新 ...

  9. 一文搞懂│mysql 中的备份恢复、分区分表、主从复制、读写分离

    目录 mysql 的备份和恢复 mysql 的分区分表 mysql 的主从复制读写分离 mysql 的备份和恢复 创建备份管理员 创建备份管理员,并授予管理员相应的权限 备份所需权限:select,r ...

随机推荐

  1. 嵌入式的我们为什么要学ROS

  2. 记一次由sql注入到拿下域控的渗透测试实战演练(下)

    本次渗透使用工具: mimikatz,PsExec 本次渗透网络拓扑图: 开始渗透: 上一篇文章中我们讲到我们成功渗透了目标内网中web服务器并提取其管理员明文密码,通过明文密码又成功登陆了内网中的另 ...

  3. D - Wireless Network(无线网络)

    题意:给你 N 台坏了的电脑的坐标 ,和一个距离范围 d . (在距离范围内的电脑可以相互通信,每台电脑也可以连接两台不同的电脑,使他们之间能够通信) 输入任意次数操作: O   x        表 ...

  4. PTA甲级—链表

    1032 Sharing (25分) 回顾了下链表的基本使用,这题就是判断两个链表是否有交叉点. 我最开始的做法就是用cnt[]记录每个节点的入度,发现入度为2的节点即为答案.后来发现这里忽略了两个链 ...

  5. HDU6403 Card Game【基环树 + 树形DP】

    HDU6403 Card Game 题意: 给出\(N\)张卡片,卡片正反两面都有数字,现在要翻转一些卡片使得所有卡片的正面的值各不相同,问最小翻转次数和最小翻转情况下的不同方案数 \(N\le 10 ...

  6. QQ空间自动点赞js代码

    1.jQuery().each(): each() 方法为每个匹配元素规定要运行的函数. 提示:返回 false 可用于及早停止循环. 函数原型: function(index,element) 为每 ...

  7. c# grpc

    刚接触RPC时只知道概念是远程过程调用协议,分为服务端和客户端,客户端请求服务端,服务端再回应客户端,粗看和HTTP一应一答没有什么区别.既然有着存在即合理的说法,网上找找说法,有的讲的太深感觉太啰嗦 ...

  8. Nginx基础 - HTTPS安全web服务

    1.HTTPS配置语法 Syntax: ssl on | off; Default: ssl off; Context: http, server Syntax: ssl_certificate fi ...

  9. 2019牛客多校第一场I Points Division(DP)题解

    题意: n个点,分成两组A,B,如果点i在A中,那么贡献值\(a_i\),反之为\(b_i\). 现要求任意\(i \in A,j \in B\)不存在 \(x_i >= x_j\) 且 \(y ...

  10. Asp.Net Core Grpc 入门实践

    Grpc简介 gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架. 在 gRPC 中,客户端应用程序可以直接调用不同计算机上的服务器应用程序上的方法,就像它是本地对象一样,从而更轻松地创 ...