更高效的查询以避免 Hive 中的 OutOfMemoryError

More efficient query to avoid OutOfMemoryError in Hive

我在 Hive 中遇到异常:

java.lang.OutOfMemoryError: GC overhead limit exceeded.

在搜索中我发现这是因为所有 CPU 过程中 98% 的时间都将用于垃圾收集(不管那是什么意思?)。我的问题的核心在我的查询中吗?我是否应该以不同的方式编写以下内容以避免此类问题?

我正在计算在给定时间段内有多少特定 phone 类型具有活跃的 'Use'。有没有办法以不同的方式执行此逻辑,这会 运行 更好?

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

谢谢

为了提高性能,通过查看您的查询:我将按 yyyy, mm, ddimei 的前两位数对配置单元表进行分区,您必须根据根据您查询这些表和数据量的需要。但我会投票给 yyyy, mm, dd,这会给你带来巨大的性能改进。见 improving-query-performance-using-partitioning

但是现在,这应该会给您带来一些改进:

Select count(distinct(pd.imei))
from pingdata pd join eventdata ed on pd.imei=ed.imei
where 
TO_DATE(pd.timestamp) between '2016-06-01' AND '2016-07-17'
and pd.timestamp=ed.pd.timestamp
and SUBSTR(pd.imei,12,2) in ('04','05') 
and ed.event = 'Use' AND ed.clientversion like '3.2%';

如果 TO_DATE(timestamp) 值在同一天插入,换句话说,如果日期的两个值相同,则应排除 and pd.timestamp=ed.pd.timestamp 条件。

Select count(distinct(pd.imei))
from pingdata pd join eventdata ed on pd.imei=ed.imei
where 
TO_DATE(pd.timestamp) between '2016-06-01' AND '2016-07-17'
and SUBSTR(pd.imei,12,2) in ('04','05') 
and ed.event = 'Use' AND ed.clientversion like '3.2%';

尝试 运行 两个查询并比较结果。如果您觉得这有帮助,请告诉我们不同之处。

在加入每个数据集之前对它们应用 distinct 更安全,因为加入非唯一键会复制数据。

我建议按 to_date(timestamp) 字段 (yyyy-MM-dd) 对您的数据集进行分区,以便根据您的 where 子句进行分区修剪(检查是否有效)。如果数据集太大并且包含大量事件 <> 'Use' 的数据,也可以按事件字段进行分区。

了解它在哪个阶段失败很重要。还要研究异常。如果它在映射器上失败,那么你应该优化你的子查询(如我提到的那样添加分区)。如果它在 reducer (join) 上失败,那么你应该以某种方式改进 join(尝试减少每个 reducer 的字节数:

set hive.exec.reducers.bytes.per.reducer=67108864; 或什至更少)如果它在 writer 上失败(OrcWriter 然后尝试通过 imei 的 substr 将分区添加到输出 table 和'distribute by substr(imei...)` 在查询结束以减轻减速器的压力)。

或者添加更多低基数和均匀分布的列,以在更多 reducer 之间均匀分布数据:

distribute by substr(imei...), col2

确保分区列在分配依据中。这将减少每个 reducer 写入的文件数量并有助于摆脱 OOM