一、Hive 数据分区
1,Hive 数据分区的概念
在Hive Select查询中一般会扫描整个表内容,会消耗很多时间做没必要的工作。有时候只需要扫描表中关心的一部分数据,因此建表时引入了partition概念。Hive的分区是为了辅助查询,缩小查询范围,加快数据的检索速度和对数据按照一定的规格和条件进行管理。
2,分区的意义
现在科技的发展,数据量越来越大了,所以大数据平台基于HDFS在处理数据的时候就比较困难,Hive用SQL代码转换MapReduce 作业,并提交到 Hadoop 集群执行。Hve的分区表将数据分成多个分区,每个分区对应一个分区列的值,每个分区在 HDFS 里面其实就是表目录下的一个子目录。如果在查询的时候只需要特定分区的数据,那么 Hive 只会遍历该分区目录下的数据。这样能够可以避免全表扫描减低 IO,提升查询性能。
3,分区表的创建
CREATE TABLE table_name (column1 data_type, column2 data_type)
PARTITIONED BY (partition1 data_type, partition2 data_type,….);
// PARTITIONED BY Hive表分区关键字
4,Hive 分区类型
(1)动态分区
- 对分区表的一次性插入称为动态分区。
- 动态分区表从非分区表加载数据。
- 在加载数据的时候,动态分区比静态分区会消耗更多时间。
- 如果需要存储到表的数据量比较大,那么适合用动态分区。
- 假如要对多个列做分区,但又不知道有多少个列,那么适合使用动态分区。
- 动态分区不需要 where 子句使用 limit,不能对动态分区执行修改。
- 可以对内部表和外部表使用动态分区。
- 使用动态分区之前,需要把模式修改为非严格模式。set hive.mapred.mode=nostrict。
(2)静态分区
- 把输入数据文件单独插入分区表的叫静态分区。
- 通常在加载文件(大文件)到 Hive 表的时候,首先选择静态分区。
- 在加载数据时,静态分区比动态分区更节省时间。
- 可以通过 alter table add partition 语句在表中添加一个分区,并将文件移动到表的分区中。
- 可以修改静态分区中的分区。
- 可以从文件名、日期等获取分区列值,而无需读取整个大文件。
- 如果要在 Hive 使用静态分区,需要把 hive.mapred.mode 设置为 strict,set hive.mapred.mode=strict。
- 可以在 Hive 的内部表和外部表使用静态分区。
5,Hive 分区的优点与缺点
(1)Hive 分区优点
- Hive 的分区可以水分分散执行压力。
- 数据查询性能比较好。
- 不需要在整个表列中搜索单个记录。
(2)Hive 分区缺点
- 创建太多的小分区,也就是说可能会创建很多目录。
- 分区对于低容量数据是有效的,但有些查询比如对大的数据量进行分组需要消耗很长时间。
二、Hive 分桶
1,Hive 分桶的概念
对于每一个表或者分区, Hive可以进一步组织成桶,也就是说分桶是更为细粒度的数据范围划分。Hive会计算桶列的哈希值再以桶的个数取模来计算某条记录属于那个桶。
2,分桶的意义
Hive分桶是为了获得更高的查询处理效率。桶为表加上了额外的结构,Hive在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用Map端连接(Map-side join)高效的实现。
分桶可以使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
分区不可能适用于所有场景。比如,基于地理位置(比如:国家)对表进行分区时,某些较大的国家将会具有较大分区,可能有四五个国家的数量占了所有数据的 70-80%。而小国家的数据创建的分区则比较小。那么这时,给表做分区就不是个好主意。为了解决分区不平衡的问题,Hive 提出了分桶的概念。它是另一种针对表数据划分的技术。
3,分区表的创建和插入数据
(1)创建分桶表
CREATE TABLE bucketed_user(
firstname VARCHAR(64),
lastname VARCHAR(64),
address STRING,
city VARCHAR(64),
state VARCHAR(64),
post STRING,
phone1 VARCHAR(64),
phone2 STRING,
email STRING,
web STRING
)
COMMENT 'A bucketed sorted user table'
PARTITIONED BY (country VARCHAR(64))
CLUSTERED BY (state) SORTED BY (city) INTO 32 BUCKETS
STORED AS SEQUENCEFILE;
//每个分区创建了 32 个桶。需要注意的是分桶字段和排序字段需要出现在列定义中,而分区字段不能出现在列定义列表里面。
(2)分桶表插入数据
分桶表或者分区表加载数据时,不能直接使用 load data 命令。必须要用 insert overwrite table … select … from 语句从其他表把数据加载到分桶分区表。所以我们需要在 Hive 创建一个临时表来先把数据加载进去,然后再用 insert overwrite table … select … from 语句把数据插入到 分区分桶表。
set hive.enforce.bucketing = true;
INSERT OVERWRITE TABLE bucketed_user PARTITION (country)
SELECT firstname,
lastname,
address ,
city,
state,
post,
phone1,
phone2,
email,
web,
country
FROM temp_user;
在做分区的时候,hive.enforce.bucketing = true 和 hive.exec.dynamic.partition=true 发挥的作用有点像。前者是自动分桶,后者是自动分区。所以在插入数据的时候,我们可以通过设置 hive.enforce.bucketing 这个属性等于 true 来启用自动分区。
自动分桶会自动把 reduce 任务数设置成等于分桶数量,而分桶数量是在 create table 的语句中设置的。如上面创建语句中为 32 个分桶。另外还会根据 CLUSTERED BY 设置的字段分桶。
如果不在 Hive 会话中把 hive.enforce.bucketing 设置为 true,那么我们必须在上面的 INSERT … SELECT 语句的前面,需要把 reduce 任务数手动设置为 32(set mapred.reduce.tasks = 32),也就是说要确保 reduce 任务数和分桶数是一致的。
4,Hive 分桶的特性
数据分桶原理是基于对分桶列做哈希计算,然后对哈希的结果和分桶数取模。
- 哈希函数取决于分桶列的类型。
- 具有相同分桶列的记录将始终存储在同一个桶中。
- 使用 clustered by 将表分成桶。
- 在表目录中,每个桶只是一个文件,并且桶的编号是从 1 开始的。
- 可以先分区再分桶,也可以直接分桶。
- 分桶表创建的数据文件大小几乎是一样的。
5,Hive 分桶的优缺点
(1)Hive 分桶的优点
- 与非分桶表相比,分桶表提供了高效采样。通过采样,我们可以尝试对一小部分数据进行查询,以便在原始数据集非常庞大时进行测试和调试。
- 由于数据文件的大小是几乎一样的,map 端的 join 在分桶表上执行的速度会比分区表快很多。在做 map 端 join 时,处理左侧表的 map 知道要匹配的右表的行在相关的桶中,因此只需要检索该桶即可。
- 分桶表查询速度快于非分桶表。
- 分桶的还提供了灵活性,可以使每个桶中的记录按一列或多列进行排序。 这使得 map 端 join 更加高效,因为每个桶之间的 join 变为更加高效的合并排序(merge-sort)。
(2)Hive 分桶的缺点
分桶并不能确保数据加载的恰当性。数据加载到分桶的逻辑需要由我们自己处理。