大家好,我是小轩
这几天看了《hive编程指南》的模式设计,整理下知识点
目录
一、按天分区表
按天划分表就是一种模式,每天一张表的方式在数据库领域是反模式的一种方式,按天划分的表建议使用分区表,hive通过where子句中的表达式来选择查询所需要的指定的分区,这样查询执行效率高。
二、关于分区
一个分区对应着一个包含有多个文件的文件夹,如果指定的表存在数百个分区,每天都会创建好几万个小文件,保持多年之后,就会超出NameNode对系统云数据信息的处理能力,因为HDFS namenode会将所有的文件系统的元数据信息加载到内存中,虽然每个文件只需要少量字节大小的元数据(大约150字节/文件)。
而且小文件容易导致处理时间长,MapReduce会将一个任务(job)转换成多个任务(task)。默认情况下,每个task都是一个新的jvm实例,jvm开启和销毁的时间中销毁可能会比实际处理数据的时间消耗要长。
分区有两种策略:
1、按时间范围进行分区。按照这个时间粒度,随着时间的推移,分区数量的增长是“均匀的”;
2、使用两个级别的分区并且使用不同的维度。如:第一个分区可能是按天(day)划分,二级分区可能通过州名(state)划分
然而有的州可能数据会多一些,就会导致map task处理数据时会出现不均匀情况,如果找不到好的、大小相对合适的分区方式,可以考虑“分桶表数据存储”
三、唯一键和标准化
hive没有主键或基于序列秘钥生成的自增键的概念,如果可以的话,应避免对非标准化数据进行连接(join)操作,复杂的数据类型,如array、map、struct,有助于实现在单行中存储一对多数据。
避免标准化的主要目的是为了最小化磁盘寻道,比如那些通常需要外键关系的情况。非标准化数据允许被扫描或写入到大的、连续的磁盘存储区域,从而优化磁盘驱动器的IO性能。但是非标准化数据可能导致数据重复,而且有更大的导致数据不一致的风险。
四、同一份数据多种处理
hive提供了一种独特的语法,可以从一个数据源产生多个数据聚合,无需每次聚合都要重新扫描一次
五、对于每个表的分区
很多的ETL处理过程会涉及到多个处理步骤,每个步骤可能会产生一个或多个临时表,这些表仅供下一个job使用,如果由于查询或者原始数据处理的某个步骤出现问题而导致需要对好几天的输入数据重跑ETL过程。
我们可以在整个过程使用分区,这样就不会存在同步问题,还可以允许用户对中间数据按日期进行比较。
但这种方法有个缺点就是需要管理中间表并删除旧分区。
六、分桶表数据存储
为了避免分区中数据不均的问题,可以用另一种数据分管的技术:分桶
create table weblog(user_id int, url string, source_id string)
partitioned by (dt string)
clustered by (user_id) into 96 buckets;
如果使用某个字段作为分桶字段,则字段值会根据用户指定的值进行哈希分发到桶中。但是,要将数据正确的插入到表的过程完全取决于用户自己!
怎么使用分桶插入数据?
(1)为分桶设置正确的reducer个数
set hive.enforce.bucketing = true;
(2)插入数据
from raw_logs
insert overwrite table weblog
partition (dt='2009-02-25')
select user_id,url,source_ip where dt='2009-02-25';
分桶的优点: (1)因为桶数量是固定的,所以他没有数据波动;
(2)桶对抽样非常适合;
(3)分桶有利于执行高效的map-side join
七、为表增加列
为表增加字段,例子: alter table weblogs add columns (user_id string);
这种方式无法再已有字段的开始或者中间增加新字段。
八、使用列存储表
hive通常使用行式存储,不过hive也提供了一个列式SerDe来以混合列式格式存储信息。某些数据集使用列式存储是最优的,如某些列重复数据特别多时,使用列式存储会加快查询速度。
九、总是使用压缩
在大多数情况下,压缩可以使磁盘上存储的数据量变小,这样可以通过降低IO来提高查询执行速度。
END