接到任务,impala查询慢。坑比较多。。。。。。
可能大家看到许多博客写优化的比较多,但我这个坑,好像没有人遇到。
优化,我也能列出一些
比如:
1.分区不能超过1w多
2.要执行compute stats xxx 表
3.join时,把小表写前面,会把小表广播到其他节点。
4.选择parquert 格式存储。
5.xxx
6.xxxxx
貌似以上这些都有用,但是在我这场景,没得用。我不是这些问题。
15:30, 我在查询时,秒出,突然刷新任务(15:40)来了,就查询不动了,基本是90秒左右,怀疑是元数据问题。
查看执行计划。
查询信息
查询 ID: a340b2e1956da5d7:f1b4ef43c875493
用户: brd
数据库: default
Coordinator: slave15
查询类型: DDL
查询状态: FINISHED
开始时间: 2017-7-12 16:43:39
结束时间: 2017-7-12 16:43:39
持续时间: 1.3分钟
Admission Result: Unknown
DDL 类型:
Impala 版本: impalad version 2.5.0-cdh5.7.1 RELEASE (build 27a4325c18c2a01c7a8097681a0eccf6d4335ea1)
Out of Memory: false
会话 ID: 484098c860a3b8d1:5034e7cb74deceaa
会话类型: HIVESERVER2
客户端获取等待时间: 3毫秒
客户端获取等待时间百分比: 1
文件格式:
查询状态: OK
缺少统计数据: false
网络地址: ::ffff:132.225.168.70:50983
规划等待时间: 1.3分钟
规划等待时间百分比: 0
连接用户: brd
Planning finished 耗时长,其实它的前一步是 元数据信息刷新,对比,验证。
源码分析
result.setQuery_exec_request(queryExecRequest);
if (analysisResult.isQueryStmt()) {
// fill in the metadata
LOG.debug("create result set metadata");
result.stmt_type = TStmtType.QUERY;
result.query_exec_request.stmt_type = result.stmt_type;
TResultSetMetadata metadata = new TResultSetMetadata();
QueryStmt queryStmt = analysisResult.getQueryStmt();
int colCnt = queryStmt.getColLabels().size();
for (int i = 0; i < colCnt; ++i) {
TColumn colDesc = new TColumn();
colDesc.columnName = queryStmt.getColLabels().get(i);
colDesc.columnType = queryStmt.getResultExprs().get(i).getType().toThrift();
metadata.addToColumns(colDesc);
}
result.setResult_set_metadata(metadata);
} else {
Preconditions.checkState(analysisResult.isInsertStmt() ||
analysisResult.isCreateTableAsSelectStmt());
// For CTAS the overall TExecRequest statement type is DDL, but the
// query_exec_request should be DML
result.stmt_type =
analysisResult.isCreateTableAsSelectStmt() ? TStmtType.DDL : TStmtType.DML;
result.query_exec_request.stmt_type = TStmtType.DML;
// create finalization params of insert stmt
InsertStmt insertStmt = analysisResult.getInsertStmt();
if (insertStmt.getTargetTable() instanceof HdfsTable) {
TFinalizeParams finalizeParams = new TFinalizeParams();
finalizeParams.setIs_overwrite(insertStmt.isOverwrite());
finalizeParams.setTable_name(insertStmt.getTargetTableName().getTbl());
finalizeParams.setTable_id(insertStmt.getTargetTable().getId().asInt());
String db = insertStmt.getTargetTableName().getDb();
finalizeParams.setTable_db(db == null ? queryCtx.session.database : db);
HdfsTable hdfsTable = (HdfsTable) insertStmt.getTargetTable();
finalizeParams.setHdfs_base_dir(hdfsTable.getHdfsBaseDir());
finalizeParams.setStaging_dir(
hdfsTable.getHdfsBaseDir() + "/_impala_insert_staging");
queryExecRequest.setFinalize_params(finalizeParams);
}
}
validateTableIds(analysisResult.getAnalyzer(), result);
timeline.markEvent("Planning finished");
result.setTimeline(analysisResult.getAnalyzer().getTimeline().toThrift());
return result;
}
Catalogd进程是Impala中用来传递Impala SQL导致的元数据变化的组件,它把这些变化传递给集群中所有的节点。一个集群中只需要一个节点上有这个守护进程,因为请求是通过Statestore传递的,因此Statestored和Catalogd 服务应当运行在同一节点上
所以后来查询问题,找到了,在刷新前查询很快,刷新后,查询不动了。
然后再看怎么刷新的,
问题找到了,每次执行都是invalidate metadata;
去掉后,查询秒出,问题解决。
总结:
1.invalidate metadata 最好后面跟上表,禁止单独执行该语句(什么都不跟)。
2. 外部表,如果是hive建立分区,那就需要刷新,刷新是在元数据中更新分区信息。更新过了,直接放入数据。