【问题标题】:hive: filter by "max(partitioned_col)" without performing full table scanhive:按“max(partitioned_col)”过滤而不执行全表扫描
【发布时间】:2015-08-13 18:05:29
【问题描述】:

我有一个按日期分区的大型 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))?

【问题讨论】:

    标签: hive hiveql


    【解决方案1】:

    您是否对查询运行了 EXPLAIN,以了解 Hive 如何尝试将该 JOIN 转换为子任务?

    好吧,EXPLAIN 输出是一团糟,但我怀疑它会显示一个尴尬的查询计划,例如......

    • 整个左侧表转储到每个 Mapper 的 RAM(即 Java HashMap)中
    • 然后依次读取 右侧 子查询(1 条记录)的结果,以将每条记录与 HashMap 进行匹配

    这是典型的 MAPJOIN 顺序错误。 那么,用更明确的WHERE IN (subquery)supported at last in Hive 0.13 替换那个虚拟的JOIN 怎么样?

    底线:Hive 查询优化器仍然是一头粗暴而凶恶的野兽。在许多情况下,您必须将其引导至“正确”的查询计划。

    【讨论】:

      【解决方案2】:

      这个查询给出了最大值(分区列)而不扫描整个表。

      hive -e "set hive.cli.print.header=false;show partitions table_name;" | tail -1 | cut -d'=' -f2
      

      【讨论】:

      • 如何将此值提供给从另一个程序(例如 HUE)执行的查询?据我了解,这将再次需要某种自定义值注入。
      • 是的..您必须通过这种方法通过 shell 脚本使用值注入。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-11
      • 1970-01-01
      相关资源
      最近更新 更多