一、概述
hive表进行分区设置对于表的读写性能有较大影响。本文主要介绍hive中一中最常见的分区类型,即通过日期时间字段进行分区的策略,以及不同策略之间见查询的性能影响。
根据日期时间字段进行分区有两种常见的策略:
1.水平分区(flat)
2.嵌套分区(nested)
-
所谓的水平分区,故名思义则是将year-month-day看作一个整体。比如说日期2018-12-25,假设分区字段为名为date,那么最终的partition则为’date=2018-12-25’。
-
而嵌套分区,则是将年(year)、月(month)、日(day)拆开,那么最终的分区结构为三级结构’year=2018/month=12/day=25’
二、策略选择
不同的分区方式对查询的性能有重大影响,在选择不同的分区方式时主要要考虑一下两点:
- 查询性能和元数据(metadata)扩展性的平衡
查询性能自然不用多说,元数据的扩展性则体现在HDFS对文件的管理。有时候分区越细往往意味着文件越多,那么HDFS的schemes就越大,管理越困难。而且分区越多也就意味着hive的metastore中相应的分区信息也越多。
所以,如果你的查询更多地时候是具体到某一天,那么建议采用水平分区,这样不仅快而且hive的metastore压力会更小;如果更多地时候是统计某个月或者某一年的数据,那么建议采用嵌套分区。
- 时间戳兼容性的平衡
关于时间戳兼容性,即考虑采用那种方式时还应该考虑数据源的时间格式。 需要关注来自给定源的数据是具有以单个yyyymmdd 类似格式组合的时间戳,还是已经将日期解析为单独的yyyy,mm和dd字段。 在Hive中,将表的分区与数据源的字段对齐通常能够带来很大的方便, 否则,查询最终会变得困难。 例如,如果源系统具有“水平分区”日期并且Hive表是“嵌套”,则针对Hive表的查询通常最终会有一堆“子字符串”表达式来挑选要在查询中使用的日期。
三、应用举例
下面以这几个日期时间(2015-01-01, 2015-02-03,2016-01-01)为例具体展示二者之间的区别:
表 A, 根据DateStamp字符串 "YYYY-MM-DD"进行分区
表 B, 根据 YEAR INT, Month INT, Day INT进行嵌套分区
在A表上进行查询:
查询所有日期
SELECT * FROM TableA WHERE DateStamp IN (‘2015-01-01’, ‘2015-02-03’, ‘2016-01-01’)
只查询2015年
SELECT * FROM TableA WHERE DateStamp LIKE ‘2015-%’
只查2015年2月
SELECT * FROM TableA WHERE DateStamp LIKE ‘2015-02-%’
所有日期天中包含5的
SELECT * FROM TableA WHERE DateStamp LIKE ‘%-%-%5’
介于2015-01-01 和 2015-03-01
SELECT * FROM TableA WHERE DateStamp BETWEEN ‘2015-01-01’ AND ‘2015-03-01’
在表B上进行查询
查询所有日期
SELECT * FROM TableB WHERE (YEAR=2015 AND MONTH=01 AND DAY=01) OR (YEAR=2015 AND MONTH=02 AND DAY=03) OR (YEAR=2016 AND MONTH=01 AND DAY=01)
只查询2015年
SELECT * FROM TableB WHERE YEAR=2015
只查2015年2月
SELECT * FROM TableB WHERE YEAR=2015 and MONTH=02
所有日期天中包含5的
SELECT * FROM TableB WHERE DAY LIKE ‘%5’
介于2015-01-01 和 2015-03-01
SELECT * FROM TableA WHERE YEAR=2015 and ((MONTH=01 OR MONTH=02) OR (MONTH =03 and DAY =01))
在上述情况中第一种方式是比较有优势的,尤其是对于使用hive的人来说他可能并不清楚你到底是怎么进行分区的,那么第一种方式就更接近于人们日常的使用习惯。原因在于这种基于时间的一级分区相比于多级分区能够更好的支持类似like、in、between等SQL语句。
四、扩展
那么问题来了,如果我就是想采用嵌套的方式进行分区,同时又想拥有一级分区所带来的好处那么该怎么办呢?
借鉴一级分区的思想,在采用嵌套分区(年/月/日)方法时,可以在下一级分区前带上上一级分区的信息。
举例说明:
以日期“2015-01-01”为例,若要采用三级分区,同时兼顾一级分区的优势,在构建分区时可以采用(year/year-month/year-month-day)的结构,对应2015-01-01的分区结构则为2015/2015-01/2015-01-01的三级分区结构。