2

我刚刚了解了 Hive 中的 collect_set() 函数,并开始在开发 3 节点集群上工作。

我只有大约 10 GB 的空间要处理。然而,这项工作实际上是永远的。我认为 collect_set() 的实现中可能存在错误,我的代码中存在错误,或者 collect_set() 函数确实是资源密集型的。

这是用于 Hive 的我的 SQL(没有双关语):

INSERT OVERWRITE TABLE sequence_result_1
SELECT sess.session_key as session_key,
       sess.remote_address as remote_address,
       sess.hit_count as hit_count,
       COLLECT_SET(evt.event_id) as event_set,
       hit.rsp_timestamp as hit_timestamp,
       sess.site_link as site_link
    FROM site_session sess 
        JOIN (SELECT * FROM site_event 
                WHERE event_id = 274 OR event_id = 284 OR event_id = 55 OR event_id = 151) evt 
            ON (sess.session_key = evt.session_key)
        JOIN site_hit hit ON (sess.session_key = evt.session_key)
GROUP BY sess.session_key, sess.remote_address, sess.hit_count, hit.rsp_timestamp, sess.site_link
ORDER BY hit_timestamp;

有 4 个 MR 通行证。第一个大约需要 30 秒。第二张地图用了大约 1 分钟。第二次减少的大部分时间大约需要 2 分钟。在过去的两个小时内,它从 97.71% 增加到 97.73%。这是正确的吗?我想一定有什么问题。我看了看日志,不知道是否正常。

[日志样本]

2011-06-21 16:32:22,715 WARN org.apache.hadoop.hive.ql.exec.GroupByOperator: Hash Tbl flush: #hash table = 120894
2011-06-21 16:32:22,758 WARN org.apache.hadoop.hive.ql.exec.GroupByOperator: Hash Table flushed: new size = 108804
2011-06-21 16:32:23,003 INFO org.apache.hadoop.hive.ql.exec.JoinOperator: 4 forwarding 5142000000 rows
2011-06-21 16:32:23,003 INFO org.apache.hadoop.hive.ql.exec.SelectOperator: 5 forwarding 5142000000 rows
2011-06-21 16:32:24,138 INFO org.apache.hadoop.hive.ql.exec.JoinOperator: 4 forwarding 5143000000 rows
2011-06-21 16:32:24,138 INFO org.apache.hadoop.hive.ql.exec.SelectOperator: 5 forwarding 5143000000 rows
2011-06-21 16:32:24,725 WARN org.apache.hadoop.hive.ql.exec.GroupByOperator: Hash Tbl flush: #hash table = 120894
2011-06-21 16:32:24,768 INFO org.apache.hadoop.hive.ql.exec.GroupByOperator: 6 forwarding 42000000 rows
2011-06-21 16:32:24,771 WARN org.apache.hadoop.hive.ql.exec.GroupByOperator: Hash Table flushed: new size = 108804
2011-06-21 16:32:25,338 INFO org.apache.hadoop.hive.ql.exec.JoinOperator: 4 forwarding 5144000000 rows
2011-06-21 16:32:25,338 INFO org.apache.hadoop.hive.ql.exec.SelectOperator: 5 forwarding 5144000000 rows
2011-06-21 16:32:26,467 INFO org.apache.hadoop.hive.ql.exec.JoinOperator: 4 forwarding 5145000000 rows
2011-06-21 16:32:26,468 INFO org.apache.hadoop.hive.ql.exec.SelectOperator: 5 forwarding 5145000000 rows

我对此很陌生,尝试使用 collect_set() 和 Hive Array 让我远离了深渊。

提前致谢 :)

4

3 回答 3

2

重大失败。我的解决方案如下。毕竟 COLLECT_SET 没有问题,它只是试图收集所有项目,其中有无限。

为什么?因为我加入了一些甚至不属于系列的东西。第二个连接曾经是相同的 ON 条件,现在它正确地说hit.session_key = evt.session_key

INSERT OVERWRITE TABLE sequence_result_1
SELECT sess.session_key as session_key,
       sess.remote_address as remote_address,
       sess.hit_count as hit_count,
       COLLECT_SET(evt.event_id) as event_set,
       hit.rsp_timestamp as hit_timestamp,
       sess.site_link as site_link
    FROM tealeaf_session sess 
        JOIN site_event evt ON (sess.session_key = evt.session_key)
        JOIN site_hit hit   ON (sess.session_key = hit.session_key)
    WHERE evt.event_id IN(274,284,55,151)
GROUP BY sess.session_key, sess.remote_address, sess.hit_count, hit.rsp_timestamp, sess.site_link
ORDER BY hit_timestamp;
于 2011-06-22T16:06:30.277 回答
0

我要尝试的第一件事是摆脱子选择并加入到 site_event,然后将 event_id 过滤器移动到外部 where 子句并将其更改为 in()。所以像:

SELECT sess.session_key as session_key,
   sess.remote_address as remote_address,
   sess.hit_count as hit_count,
   COLLECT_SET(evt.event_id) as event_set,
   hit.rsp_timestamp as hit_timestamp,
   sess.site_link as site_link
FROM site_session sess 
    JOIN site_event evt ON (sess.session_key = evt.session_key)
    JOIN site_hit hit ON (sess.session_key = evt.session_key)
WHERE evt.event_id in(274,284,55151)
GROUP BY sess.session_key, sess.remote_address, sess.hit_count, hit.rsp_timestamp, sess.site_link
ORDER BY hit_timestamp;

此外,我不知道每个表的大小,但通常在 Hive 中,您希望将最大的表(通常是事实表)保留在连接的右侧以减少内存使用。原因是 Hive 尝试将连接的左侧保存在内存中,并流式传输右侧以完成连接。

于 2011-06-22T00:06:59.673 回答
0

我猜想发生的事情是它正在COLLECT_SET()为每个将返回的行生成一个。因此,对于您返回的每一行,它都会返回由COLLECT_SET. 这可能会很费力并且需要很长时间。

在查询之外检查性能COLLECT_SET。如果这足够快,请将计算推COLLECT_SET入子查询,然后使用该列而不是在您所在的位置进行计算。

我没有使用 COLLECT_SET 或做过任何测试,从你的帖子来看,这是我首先怀疑的。

于 2011-06-22T01:09:25.360 回答