我在Hive里遇到了一个例外:
java.lang.outofmemoryerror:超出gc开销限制。
在搜索过程中,我发现这是因为进程中98%的cpu时间都要进行垃圾收集(不管这意味着什么?)。我的问题的核心是什么?我是否应该用另一种方式写下面的内容来避免这种问题?
我试着计算在给定的时间段内有多少特定类型的手机在使用。有没有一种不同的方法来实现这个逻辑,这样会运行得更好?
select count(a.imei)
from
(Select distinct imei
from pingdata
where timestamp between TO_DATE("2016-06-01") AND TO_DATE("2016-07-17")
and ((SUBSTR(imei,12,2) = "04") or (SUBSTR(imei,12,2) = "05")) ) a
join
(SELECT distinct imei
FROM eventdata
where timestamp between TO_DATE("2016-06-01") AND TO_DATE("2016-07-17")
AND event = "Use" AND clientversion like '3.2%') b
on a.imei=b.imei
谢谢您
2条答案
按热度按时间vlf7wbxs1#
在加入每个数据集之前对它们应用distinct更安全,因为加入非唯一键会复制数据。
我建议按tou date(timestamp)字段(yyyyy-mm-dd)对数据集进行分区,以便根据where子句进行分区修剪(检查是否有效)。如果数据集太大,并且包含大量的数据,而event<>“use”则按事件字段进行分区。
知道它在哪个阶段失败是很重要的。也要研究例外情况。如果它在Map器上失败,那么您应该优化您的子查询(如我所述添加分区)。如果它在reducer(join)上失败,那么您应该以某种方式改进join(尝试减少每个reducer的字节数:
set hive.exec.reducers.bytes.per.reducer=67108864;
或者更少)如果它在writer上失败(或者writer然后尝试通过imei中的substr和查询末尾的“distribute by substr(imei…)”将分区添加到输出表中,以减少减压器的压力)。或者添加一个或多个基数低且分布均匀的列,以便在多个缩减器之间均匀分布数据:
确保分区列位于分发方式中。这将减少每个reducer编写的文件数量,并有助于消除oom
dy2hfwbg2#
为了提高性能,通过查看您的查询:我将按
yyyy, mm, dd
,或按imei
,则必须根据查询这些表的需要和数据量来决定变量。但我会投票给yyyy, mm, dd
,这将给您带来巨大的性能改进。请参阅使用分区提高查询性能但现在,这应该会给你一些改进:
如果
TO_DATE(timestamp)
值是在同一天插入的,换句话说,如果两个值对于date than是相同的and pd.timestamp=ed.pd.timestamp
应排除条件。尝试运行两个查询并比较结果。一定要让我们知道区别,如果你觉得这有帮助。