我有一个按日期分区的大型Hive表,我正在尝试设置一个Oozie工作流,该工作流在最近的分区上运行一个进程。每次ETL作业运行时,都会创建一个新文件夹。目录结构如下所示:
/user/hive/warehouse/my_transactions/date=20150424
[...]
/user/hive/warehouse/my_transactions/date=20150811
/user/hive/warehouse/my_transactions/date=20150812
/user/hive/warehouse/my_transactions/date=20150813
在我的家庭/实验室群集上运行Hive 1.1.0-cdh5.4.4,我可以在子查询中使用max
聚合函数来过滤最近几天的数据:
select
[...]
from my_transactions
inner join (select max(date) as max_date from my_transactions) max_date
on date = max_date
结果很快就会返回。
在我们的工作环境中,使用更强大的硬件在更大的数据集上运行Hive 0.13.0-mapr-1501,同一查询尝试在多个阶段执行,最终抛出java.lang.OutOfMemoryError: Java heap space
。
如果我用文字替换子查询,即WHERE date = '20150813'
而不是聚合和内连接,它会很快执行。使用聚合/子查询,而不是使用分区来减少IO的数量,它正在尝试扫描所有分区。
是否有更好的方法来编写此查询(例如,可能会查询Hive元数据以获取分区列的max(date)
)?
答案 0 :(得分:2)
您是否对查询运行了一个EXPLAIN,以了解Hive如何尝试将该JOIN转换为子任务?
好吧,EXPLAIN输出是一个脏乱,但我怀疑它会显示一个尴尬的查询计划,如......
这是典型的错误顺序的MAPJOIN。
那么,用supported at last in Hive 0.13更明确的JOIN
取代虚假WHERE IN (subquery)
呢?
底线:Hive查询优化器仍然是一个粗暴恶毒的野兽。在许多情况下,你必须把它引导到"纠正"查询计划。
答案 1 :(得分:0)
此查询提供max(分区列)而不扫描整个表。
hive -e "set hive.cli.print.header=false;show partitions table_name;" | tail -1 | cut -d'=' -f2