一、分区概述
- 传统的OLTP数据库一般都具有索引和表分区的功能,通过表分区能够在特定的区域检索数据,减少扫描成本,在一定程度上提高查询效率,还可以通过建立索引进一步提升查询效率。在Hive数仓中也有索引和分区的概念。
- 分区是一种根据“分区列”(partition column)的值对表进行粗略划分的机制。Hive中每个分区对应着表很多的子目录,将所有的数据按照分区列放入到不同的子目录中去。
二、为什么要分区
- 庞大的数据集可能需要耗费大量的时间去处理。在许多场景下,可以通过分区的方法减少每一次扫描总数据量,这种做法可以显著地改善性能。
- 为了达到性能表现的一致性,对不同列的划分应该让数据尽可能均匀分布。最好的情况下,分区的划分条件总是能够对应where语句的部分查询条件,这样才能充分利用分区带来的性能优势。
- Hive的分区使用HDFS的子目录功能实现。每一个子目录包含了分区对应的列名和每一列的值。
- Hive查询通常使用分区的列作为查询条件。这样的做法可以指定MapReduce任务在HDFS中指定的子目录下完成扫描的工作。HDFS的文件目录结构可以像索引一样高效利用。
- Hive(Inceptor)分区包括静态分区和动态分区。
三、静态分区
-
根据插入时是否需要手动指定分区可以分为:
- 静态分区:导入数据时需要手动指定分区。
- 动态分区:导入数据时,系统可以动态判断目标分区。
-
创建静态分区
- 直接在 PARTITIONED BY 后面跟上分区键、类型即可。(分区键不能和任何列重名)
-- 分区字段主要是时间,按年分区 create table device_open( deviceid varchar(50), ... ) partitioned by (year varchar(50)) row format delimited fields terminated by '\t';
-
写入数据
-- 覆盖写入 -- insert overwrite table device_open partition (year='2020') -- 追加写入 insert into table device_open partition (year='2020') select ..., original_device_open.month as month, original_device_open.day as day, original_device_open.hour as hour from original_device_open
四、动态分区
-
创建动态分区
-- 分区字段主要是时间,分为年、月、日、时 create table device_open( deviceid varchar(50), ... ) partitioned by ( year varchar(50), month varchar(50), day varchar(50), hour varchar(50)) row format delimited fields terminated by '\t';
-
写入动态分区
-- 开启动态分区支持,并开启非严格模式 set hive.exec.dynamic.partition=true; set hive.exec.dynamic.partition.mode=nonstrict; insert overwrite table device_open partition (year, month, day, hour) select ..., original_device_open.year as year, original_device_open.month as month, original_device_open.day as day, original_device_open.hour as hour from original_device_open;
五、动态分区和静态分区混用
-
一张表可同时被静态和动态分区键分区,只是动态分区键需要放在静态分区键的后面(因为HDFS上的动态分区目录下不能包含静态分区的子目录)。
-
静态分区键要指定分区值;动态分区只需要给出分区键名称
insert overwrite table devicec_open partition (year='2017', month='05', day, hour) select ..., original_device_open.day as day, original_device_open.hour as hour from original_device_open where original_device_open.year='2017' and original_device_open.month='05';
六、有序动态分区
注意,如果个人电脑性能不好,出现因为动态分区而导致的内存溢出问题,可以设置hive.optimize.sort.dynamic.partition进行避免
设置为true后,当启用动态分区时,reducer仅随时保持一个记录写入程序,从而降低对
reducer产生的内存压力。但同时也会使查询性能变慢。
动态分区其他相关属性设置: