Hive故障排查备忘录

工作中使用Hive时,遇到过各种各样的问题与异常。本着追根朔源、从挫折中不断学习的原则,以后我会将全部遇到的问题记录在这里备忘。
同时也督促自己面向问题时寻根刨地,不轻言放弃。

错误代码:20004

错误描述

Fatal error occurred when node tried to create too many dynamic partitions.
The maximum number of dynamic partitions is controlled by hive.exec.max.dynamic.partitions and hive.exec.max.dynamic.partitions.pernode.
Maximum was set to: xxx

错误原因

当执行select into操作时,如果into目标数据表是动态分区的话,就有可能出现这个错误。

以下hive源代码可以很直观地看出来20004错误发生的原因:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
protected FSPaths getDynOutPaths(List<String> row, String lbDirName) throws HiveException {

FSPaths fp;

// get the path corresponding to the dynamic partition columns,
String dpDir = getDynPartDirectory(row, dpColNames);

String pathKey = null;
if (dpDir != null) {
dpDir = appendToSource(lbDirName, dpDir);
pathKey = dpDir;
if (conf.getDpSortState().equals(DPSortState.PARTITION_BUCKET_SORTED)) {
String buckNum = row.get(row.size() - 1);
taskId = Utilities.replaceTaskIdFromFilename(Utilities.getTaskId(hconf), buckNum);
pathKey = appendToSource(taskId, dpDir);
}
FSPaths fsp2 = valToPaths.get(pathKey);

if (fsp2 == null) {
// check # of dp
if (valToPaths.size() > maxPartitions) {
// we cannot proceed and need to tell the hive client that retries won't succeed either
throw new HiveFatalException(
ErrorMsg.DYNAMIC_PARTITIONS_TOO_MANY_PER_NODE_ERROR.getErrorCodedMsg()
+ "Maximum was set to: " + maxPartitions);
}
// ......
}

以上代码可以看出来,Hive执行Job时会检查输出的动态分区数量。

注意,这个动态分区数量并不是目录的数量,而是输出的数据文件数量。
即如果你select into的是一个日期分区,但是如果数据量大的话,还是会有可能出现几十几百个数据文件,导致valToPaths.size()大于maxPartitions,印发这个异常。

解决办法

既然错误抛出的原因是valToPaths.size()大于maxPartitions,而valToPaths.size()无法减小,并且随着时间迁移还可能越来越大,那么解决这个错误就只能增大maxPartitions的值了。

maxPartitions取值来源如下:

1
2
DYNAMICPARTITIONMAXPARTSPERNODE("hive.exec.max.dynamic.partitions.pernode", 100,
"Maximum number of dynamic partitions allowed to be created in each mapper/reducer node."),

那么,这个错误的解决办法就是设置hive.exec.max.dynamic.partitions.pernode为更大的值了,比如1000。