对于大型数据处理系统而言,数据分区的功能是非常重要的。因为Hive通常要对数据进行全盘扫描,才能满足查询条件(我们暂时先忽略索引的功能)。
以Hive管理大型网站的浏览日志为例。如果日志数据表不采用分区设计,那么就单日网站流量分析这样的需求而言,Hive就必然要通过遍历全量日志来完成查询。以一年日志为全量,单日查询的数据利用率将不到1%,这样的设计基本上将查询时间浪费在了数据加载中。
分区的优势在于利用维度分割数据。在使用分区维度查询时,Hive只需要加载数据,极大缩短数据加载时间。上述案例中,假使我们以日期为维度设计日志数据表的分区,对于自选日期范围的查询需求,Hive就只需加载日期范围所对应的分区数据。
由于HDFS被设计用于存储大型数据文件而非海量碎片文件,理想的分区方案不应该导致过多的分区文件,并且每个目录下的文件尽量超过HDFS块大小的若干倍。按天级时间粒度进行分区就是一个好的分区策略,随着时间的推移,分区数量增长均匀可控。此外常有的分区策略还有地域,语言种类等等。设计分区的时候,还有一个误区需要避免。关于分区维度的选择,我们应该尽量选取那些有限且少量的数值集作为分区,例如国家、省份就是一个良好的分区,而城市就可能不适合进行分区。
注意:分区是数据表中的一个列名,但是这个列并不占有表的实际存储空间。它作为一个虚拟列而存在。
分桶
分区提供了一种整理数据和优化查询的便利方式。不过,并非所有数据集都可形成合理的分区,特别是在需要合理划分数据、防止倾斜时。分桶是将数据分解管理的另一技术。
假设我们有一张地域姓名表并按城市分区。那么很有可能,北京分区的人数会远远大于其他分区,该分区的数据I/O吞吐效率将成为查询的瓶颈。如果我们对表中的姓名做分桶,将姓名按哈希值分发到桶中,每个桶将分配到大致均匀的人数。
分桶解决的是数据倾斜的问题。因为桶的数量固定,所以没有数据波动。桶对于数据抽样再适合不过,同时也有利于高效的map-side Join。
分桶与分区的关系
分区和分桶都可以单独用于表;
分区可以是多级的;
分区和分桶可以嵌套使用,但是分区必须在分桶前面。
#