#简介 zeppelin默认查询hive数据时会先获取hive的元数据,但是当元数据比较多时获取速度慢。我们的机器上show tables 会有3min中的延迟。
问题跟踪思路
执行show tables
查看zeppelin日志
从日志里可以看出当web执行脚本时实际上根据执行的任务类型调用了interpreter.sh脚本
INFO [2017-05-19 18:04:07,328] ({pool-2-thread-2} RemoteInterpreterManagedProcess.java[start]:126) - Run interpreter process [/home/hadoop/zeppelin/bin/interpreter.sh, -d, /home/hadoop/zeppelin/interpreter/jdbc, -p, 35411, -l, /home/hadoop/zeppelin/local-repo/2CGH6V1U7]
底层调用了interpreter-jdbc项目了的东西
查看hive审计日志
可以看出hive查询时除了查询需要执行的sql,还查询了其他很多元数据信息。
定位代码
通过jdbc项目中JDBCInterpreterTest.java类来测试代码,可以看到sql执行的流程,在获取Connection的时候代码有了其他操作:
propertyKeySqlCompleterMap.put(propertyKey, createSqlCompleter(connection));
根据connection创建编译器。这里边获取好多元数据信息。通过追踪createSqlCompleter()方法,发现只有两个地方调用了这个方法:
- getConnection
- open 问题就出在这里了。
解决方案,
-
1.简单粗暴的方法
注释掉这两行代码,测试后发现不影响sql执行,但是测试类自动编译方法过不去。但是整体影响不大。没有影响到zeppelin的使用 -
2.懒加载
注释掉总感觉会有其他问题。那我能不能修改代码让这部分暂时不执行,在需要的时候在执行哪?应该是可以。 大致思路 1.缓存connection和key,存储到map中 2.当调用编译方法时根据key获取对应connection ,获取元数据 3.缓存元数据到map中 -
步骤1
private Map<String,Connection> connectionMap = new HashMap<>();
private void lazyCreateCompleter(String key ,Connection conn){
connectionMap.put(key,conn);
}
- 步骤2 修改open()和getConnection()方法
//getConnection
// propertyKeySqlCompleterMap.put(propertyKey, createSqlCompleter(connection));
lazyCreateCompleter(propertyKey, connection);
//open
for (String propertyKey : basePropretiesMap.keySet()) {
//propertyKeySqlCompleterMap.put(propertyKey, createSqlCompleter(null));
lazyCreateCompleter(propertyKey, null);
}
setMaxLineResults();
- 步骤3 修改编译方法
@Override
public List<InterpreterCompletion> completion(String buf, int cursor) {
List<CharSequence> candidates = new ArrayList<>();
SqlCompleter sqlCompleter = propertyKeySqlCompleterMap.get(getPropertyKey(buf));
//当获取不到编译器时创建编译器
if(sqlCompleter == null) {
sqlCompleter = createSqlCompleter(connectionMap.get(buf));
propertyKeySqlCompleterMap.put(buf,sqlCompleter);
}
if (sqlCompleter != null && sqlCompleter.complete(buf, cursor, candidates) >= 0) {
List<InterpreterCompletion> completion;
completion = Lists.transform(candidates, sequenceToStringTransformer);
return completion;
} else {
return NO_COMPLETION;
}
}
编译代码 jdbc项目
mvn clean package -DskipTests -Dcheckstyle.skip=true
复制jar包${zeppelin_home}/interpreter/jdbc目录下,删除原来的zeppelin-jdbc-0.7.1.jar 包
重启服务
可能存在的问题
connection链接时间的问题,欢迎大神下边留言,这部分其他代码没怎么看懂。 hive sql执行没问题,但是没有测试其他sql有空大家可以测试一下