hive hms和hs2的sql执行日志分析

HMS日志:
2024-12-02 15:39:20,811 INFO org.apache.hadoop.hive.metastore.HiveMetaStore: [pool-8-thread-114]: 114: source:10.11.17.999 get_all_databases
2024-12-02 15:39:20,812 INFO org.apache.hadoop.hive.metastore.HiveMetaStore.audit: [pool-8-thread-114]: ugi=hive ip=10.11.17.999 cmd=source:10.11.17.999 get_all_databases --请求ip及请求的数据内容

HS2日志:
[HiveServer2-Handler-Pool: Thread-190281]: Using the default value passed in for log id: c095e5ef-b29a-4524-8ad3-04ba52546cbe
[HiveServer2-Handler-Pool: Thread-190281]: Updating thread name to c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281
[c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281]: Adding operation: OperationHandle [opType=EXECUTE_STATEMENT, getHandleIdentifier()=311acd89-1594-4c1b-bdbf-26de06496ced]
[c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281]: Compiling command(queryId=hive_20241202153920_217e1a21-acc4-499f-becb-12fa49ff3be8): show databases 编译开始时间 --根据sql找到位置,根据Thread-190281 查询线程运行,根据产生的queryId,往后查sql执行。
[c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281]: Semantic Analysis Completed
[c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281]: Returning Hive schema: Schema(fieldSchemas:[FieldSchema(name:database_name, type:string, comment:from deserializer)], properties:null)
[c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281]: Initializing operator LIST_SINK[0]
[c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281]: Completed compiling command(queryId=hive_20241202153920_217e1a21-acc4-499f-becb-12fa49ff3be8); Time taken: 0.014 seconds 编译结束时间
[c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281]: Using the default value passed in for log id: c095e5ef-b29a-4524-8ad3-04ba52546cbe
[c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281]: Resetting thread name to HiveServer2-Handler-Pool: Thread-190281
[HiveServer2-Background-Pool: Thread-191087]: Executing command(queryId=hive_20241202153920_217e1a21-acc4-499f-becb-12fa49ff3be8): show databases 执行sql开始!
[HiveServer2-Background-Pool: Thread-191087]: Starting task [Stage-0:DDL] in serial mode
[HiveServer2-Background-Pool: Thread-191087]: results : 12
[HiveServer2-Background-Pool: Thread-191087]: Completed executing command(queryId=hive_20241202153920_217e1a21-acc4-499f-becb-12fa49ff3be8); Time taken: 0.003 seconds 执行sql结束时间!
[HiveServer2-Background-Pool: Thread-191087]: OK
[HiveServer2-Handler-Pool: Thread-190281]: Using the default value passed in for log id: c095e5ef-b29a-4524-8ad3-04ba52546cbe
[HiveServer2-Handler-Pool: Thread-190281]: Updating thread name to c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281
。。。。。。
[c095e5ef-b29a-4524-8ad3-04ba52546cbe HiveServer2-Handler-Pool: Thread-190281]: Closing operation: OperationHandle [opType=EXECUTE_STATEMENT, getHandleIdentifier()=311acd89-1594-4c1b-bdbf-26de06496ced]

<think> 在Java中使用JDBC执行HiveSQL时,获取SQL执行日志进度信息是一个常见的需求。Hive的JDBC驱动提供了一些机制来获取这些信息。 通常,我们可以通过以下方式获取执行日志进度: 1. 使用`HiveStatement`的`getQueryLog()`方法获取执行日志2. 使用`HiveStatement`的`getQueryLog()`方法返回的日志信息,通常包含进度信息。 但是,需要注意的是,Hive JDBC驱动(特别是较新版本)可能不再支持`getQueryLog()`方法。在Hive 2.0以后,推荐使用`setLogDivertEnabled(true)`来启用日志重定向,然后通过`HiveStatement`的`getQueryLog()`方法获取日志。然而,在Hive 3.x中,`getQueryLog`方法已被标记为过时,并且可能返回空值。 因此,替代方案是使用Hive的钩子(Hook)或者通过YARN的API来获取应用程序的日志,但这超出了JDBC的范围。 下面介绍一种在Hive JDBC中获取日志进度信息的常用方法(适用于Hive 2.x,部分特性在Hive 3.x中可能不可用): 步骤: 1. 在创建连接时,设置`hive.server2.logging.operation.enabled`为`true`。 2. 在连接URL中添加参数:`hive.server2.logging.operation.enabled=true`。 3. 然后,在Statement执行之前,将Statement转换为`HiveStatement`,并调用`setLogDivertEnabled(true)`方法。 4. 执行查询后,通过`HiveStatement.getQueryLog()`获取日志。 但是,请注意:`getQueryLog()`方法返回的是从开始执行到调用该方法时的所有日志。如果查询尚未完成,那么日志可能不完整。 另外,进度信息通常以如下形式出现在日志中: `Stage-1: map = 0%, reduce = 0%` `Stage-1: map = 50%, reduce = 0%` ... 因此,我们可以定期调用`getQueryLog()`来获取最新的日志,并解析其中的进度信息。 下面是一个示例代码: 注意:需要引入Hive JDBC驱动,如`hive-jdbc`(版本要与Hive服务器匹配)。 示例代码: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.apache.hive.jdbc.HiveStatement; public class HiveJdbcWithLogs { public static void main(String[] args) throws SQLException, ClassNotFoundException { // 加载驱动 Class.forName("org.apache.hive.jdbc.HiveDriver"); // 连接URL,注意设置日志操作启用 String url = "jdbc:hive2://<hive_server2_host>:<port>/default;hive.server2.logging.operation.enabled=true"; Connection conn = DriverManager.getConnection(url, "<username>", "<password>"); try (Statement stmt = conn.createStatement()) { // 转换为HiveStatement if (stmt instanceof HiveStatement) { HiveStatement hiveStmt = (HiveStatement) stmt; // 启用日志重定向(如果驱动支持) hiveStmt.setLogDivertEnabled(true); // 异步执行查询,因为我们需要在查询执行过程中获取日志 final String sql = "SELECT * FROM your_table"; // 替换为你的查询 Thread thread = new Thread(() -> { try { // 执行查询(如果是查询,可以用executeQuery,但如果考虑到可能有DDL/DML,使用execute) boolean hasResultSet = hiveStmt.execute(sql); // 如果有结果集,可以处理结果 if (hasResultSet) { try (ResultSet rs = hiveStmt.getResultSet()) { while (rs.next()) { // 处理结果集... } } } } catch (SQLException e) { e.printStackTrace(); } }); thread.start(); // 在查询执行过程中,定期获取日志 while (thread.isAlive()) { // 每隔一段时间获取一次日志 try { Thread.sleep(1000); // 每秒获取一次 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } // 获取日志 String logs = hiveStmt.getQueryLog(); if (logs != null && !logs.isEmpty()) { System.out.println("=============================="); System.out.println(logs); System.out.println("=============================="); // 在这里解析日志,提取进度信息 // 例如:查找日志中是否包含进度百分比的字符串 } } // 线程结束后,再次获取一次确保所有日志都被捕获 String finalLogs = hiveStmt.getQueryLog(); if (finalLogs != null && !finalLogs.isEmpty()) { System.out.println(finalLogs); } } else { // 如果不是HiveStatement,则不支持获取日志 System.out.println("Statement is not HiveStatement"); } } conn.close(); } } ``` 注意: 1. 上述代码中,我们使用了一个单独的线程来执行查询,因为`execute`方法是阻塞的,所以我们在主线程中定期获取日志2. 在获取日志时,我们每秒获取一次,并打印出来。你可以根据需要解析日志中的进度信息。 3. 请替换`<hive_server2_host>`, `<port>`, `<username>`, `<password>`以及SQL语句。 然而,这种方法有以下限制: - 在Hive 3.x中,`getQueryLog`方法可能已被废弃,甚至返回空。在这种情况下,可能需要考虑其他方式,如通过YARN REST API来获取任务进度(需要知道YARN Application ID,这可以通过Hive日志或者Hive的配置来获取)。 - 另外,如果查询执行非常快,可能获取不到中间日志。 替代方案: - 使用Hive的`hive.query.id`属性,然后通过YARN的API来跟踪任务进度。但这需要额外的步骤来获取YARN应用ID,并且需要访问YARN的资源管理器。 由于Hive版本差异,上述方法可能不适用于所有情况。建议查阅所使用的Hive版本对应的JDBC驱动文档。 如果上述方法在你的Hive版本中不可用,可能需要考虑使用Hive的WebHCat或者通过HiveServer2日志文件来获取信息。 最后,请注意,频繁调用`getQueryLog()`可能会对性能有一定影响。 §§相关问题§§: 1. 在Hive JDBC中,如何获取正在执行的查询的YARN应用ID? 2. HiveStatement的setLogDivertEnabled方法有什么作用? 3. 如何通过YARN REST API获取Hive查询的进度? 4. 在Hive 3.x中,替代getQueryLog的方法是什么? </think> 在Java中使用JDBC执行Hive SQL时获取执行日志进度信息,可以通过Hive JDBC特有的`HiveStatement`类实现。以下是详细解决方案: ### 解决方案代码 ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.hive.jdbc.HiveStatement; public class HiveLogFetcher { public static void main(String[] args) { String driverName = "org.apache.hive.jdbc.HiveDriver"; String connectionURL = "jdbc:hive2://<your_hive_server>:10000/default"; String user = "<username>"; String password = "<password>"; try { // 1. 加载JDBC驱动 Class.forName(driverName); // 2. 建立连接(开启日志重定向) Connection conn = DriverManager.getConnection( connectionURL + ";hive.server2.logging.operation.enabled=true", user, password ); // 3. 创建HiveStatement HiveStatement stmt = (HiveStatement) conn.createStatement(); // 4. 启用日志重定向(关键步骤) stmt.setLogDivertEnabled(true); // 5. 执行SQL String sql = "SELECT * FROM your_table"; // 替换为你的HiveQL ResultSet rs = stmt.executeQuery(sql); // 6. 实时获取日志进度 while (rs.next() || !stmt.isClosed()) { // 获取并解析日志内容 String logs = stmt.getQueryLog(); if (logs != null && !logs.isEmpty()) { parseLogs(logs); // 自定义日志解析方法 } // 获取进度信息(如果有) String progress = stmt.getQueryPlan().getProgressUpdate(); if (progress != null) { System.out.println("Progress: " + progress); } Thread.sleep(1000); // 每秒检查一次 } // 7. 关闭资源 rs.close(); stmt.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); } } // 自定义日志解析方法(示例) private static void parseLogs(String logs) { // 示例:提取MapReduce进度 if (logs.contains("MapReduce")) { String[] lines = logs.split("\n"); for (String line : lines) { if (line.contains("map =") || line.contains("reduce =")) { System.out.println("[Job Progress] " + line.trim()); } if (line.contains("Completed executing")) { System.out.println("[Execution Completed] " + line.trim()); } } } // 输出原始日志(可选) System.out.println("Raw Logs:\n" + logs); } } ``` ### 关键原理说明 1. **日志重定向机制**: - 连接参数 `hive.server2.logging.operation.enabled=true` 启用操作日志 - `stmt.setLogDivertEnabled(true)` 将HiveServer2日志重定向到JDBC客户端 2. **日志内容解析**: - `getQueryLog()` 返回完整的执行日志(包含后台MapReduce任务进度) - 日志格式通常为: ``` Progress: Stage-1: map=50%, reduce=0% Completed executing command... ``` 3. **进度获取原理**: - Hive查询会转换为MapReduce/Tez任务 - 进度信息通过YARN资源管理器生成 - JDBC驱动通过Thrift API从HiveServer2获取实时状态 4. **注意事项**: - **驱动依赖**:需使用Hive JDBC驱动(Maven: `org.apache.hive:hive-jdbc`) - **版本兼容**:Hive 2.x+ 支持完整日志重定向,Hive 1.x功能有限 - **性能影响**:频繁获取日志会增加网络开销(建议1秒间隔) ### 日志解析要点 日志中关键进度信息示例: ``` INFO : Map 1: 0/1 Stage-1: map=0%, reduce=0% INFO : Map 1: 1/1 Stage-1: map=50%, reduce=0% INFO : Map 1: 1/1 Stage-1: map=100%, reduce=0% INFO : Reducer 2: 0/1 Stage-1: map=100%, reduce=0% INFO : Reducer 2: 1/1 Stage-1: map=100%, reduce=100% ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值