Hive中创建UDF时长时间等待

当在Hive中执行:

CREATE TEMPORARY FUNCTION ...

Hive一直处于等待,且很长时间没有结果。看上去是像在等待某个任务完成。于是顺手看了下源码。

先去下载一份相同版本的源码,简单看了下目录命名方式,和HQL相关的代码应该在ql目录中。

为了找到相关函数,根据Hive项目函数的命名风格,可以推测相关处理函数应该包含“createTemporary”关键字。用fgrep搜索下:

$ fgrep createTemporary -r -n ql/*

搜索结果中,可以看到一条定义createTemporaryFunction的语句:

ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionTask.java:169:  private int createTemporaryFunction(CreateFunctionDesc createFunctionDesc) {

打开该文件,跟踪下相关流程,该函数会调用FunctionRegistry.registerTemporaryFunction来注册函数:

boolean registered = FunctionRegistry.registerTemporaryFunction(
  createFunctionDesc.getFunctionName(),
  udfClass);

继续用fgrep跟踪FunctionRegistry.registerTemporaryFunction,在文件ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java中找到。关键代码如下:

case UDF:
  FunctionRegistry.registerTemporaryUDF(
    functionName, (Class<? extends UDF>) udfClass, false);

接着再跟踪FunctionRegistry.registerTemporaryUDF,在该函数实现中注意到:

mFunctions.put(functionName.toLowerCase(), fI);

mFunctions是个集合对象,找到它的定义:

static Map<String, FunctionInfo> mFunctions = Collections.synchronizedMap(new LinkedHashMap<String, FunctionInfo>());

可以看到mFunctions实际上是一个线程安全的Map对象,所以我猜测卡死的原因应该是因为多线程抢占的问题。

带着跟死锁有关的关键字在Google搜索了下,找到Hive的Issue列表跟我一模一样的问题:

https://issues.apache.org/jira/browse/HIVE-9203

该问题引申到另外一个Issue:https://issues.apache.org/jira/browse/HIVE-9199

从这个问题来看,确实是多线程抢占导致的。官方表示在1.1.0版本中修复这个问题,但因为是公司集群,我不能通过升级Hive来解决这个问题,于是我想有不有线程相关的配置可以解决这个问题,之后在Hive文档里找到相关设置,执行下面语句即可:

set hive.support.concurrency=false