对行进行排序时优化 Hive GROUP BY

Posted

技术标签:

【中文标题】对行进行排序时优化 Hive GROUP BY【英文标题】:Optimizing Hive GROUP BY when rows are sorted 【发布时间】:2016-12-20 17:15:48 【问题描述】:

我有以下(非常简单的)Hive 查询:

select user_id, event_id, min(time) as start, max(time) as end,
       count(*) as total, count(interaction == 1) as clicks
from events_all
group by user_id, event_id;

表格结构如下:

user_id                 event_id                time            interaction 
Ex833Lli36nxTvGTA1Dv    juCUv6EnkVundBHSBzQevw  1430481530295   0
Ex833Lli36nxTvGTA1Dv    juCUv6EnkVundBHSBzQevw  1430481530295   1
n0w4uQhOuXymj5jLaCMQ    G+Oj6J9Q1nI1tuosq2ZM/g  1430512179696   0
n0w4uQhOuXymj5jLaCMQ    G+Oj6J9Q1nI1tuosq2ZM/g  1430512217124   0
n0w4uQhOuXymj5jLaCMQ    mqf38Xd6CAQtuvuKc5NlWQ  1430512179696   1

我知道行首先按user_id 排序,然后按event_id 排序。

问题是:如果行已排序,有没有办法“提示”Hive 引擎来优化查询?优化的目的是避免将所有组保留在内存中,因为一次只需要保留一个组。

目前,在包含大约 300 GB 数据的 6 节点 16 GB Hadoop 集群中运行此查询大约需要 30 分钟,并且使用了大部分 RAM,导致系统阻塞。我知道每个组都会很小,每个 (user_id, event_id) 元组不超过 100 行,所以我认为优化的执行可能会占用非常小的内存并且速度更快(因为不需要循环组键)。

【问题讨论】:

附带说明,count(interaction == 1) 没有按我的预期工作,只计算具有 1 的行,而是返回与 count(*) 相同的行。 是的。聚合函数,包括 COUNT,忽略(仅)NULL 值并且 FALSE 不是 NULL 【参考方案1】:

创建一个分桶排序表。优化器会知道它是从元数据中排序的。 请参阅此处的示例(官方文档):https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-BucketedSortedTables

Count only interaction = 1:count(case when interaction=1 then 1 end) as clicks - case 会将所有行标记为 1 或 null,并且只计算 1。

【讨论】:

感谢@leftjoin。有几件事:首先,我的表是一个外部表,有没有办法让它工作?其次,由于它是一个外部表,因此格式是固定的(制表符分隔值,\n 终止行),并且它没有不同的组终止符等。如果问的不多,您能否提供一个使用示例我发布的具体结构? @Alejandro Piad 另请阅读:grokbase.com/t/hive/user/133xgs10cb/bucketing-external-tables 很抱歉,您似乎必须创建分桶表并插入覆盖它,如果您在现有文本文件上创建外部表,它将无法正常工作。而且移动数据需要很长时间。 是的@leftjoin,我读过的所有内容都指向这一点。我接受这是正确的答案。

以上是关于对行进行排序时优化 Hive GROUP BY的主要内容,如果未能解决你的问题,请参考以下文章

group by 优化大法

使用Order By NULL 解决 group by后自动排序,优化Sql性能

Mysql之order by|group by 排序优化

mysql GROUP BY、DISTINCT、ORDER BY语句优化

group by小结

PostgreSQL中group by中的窗口函数