从MySQL获取单个值到Java时返回0.0/Null的问题求助
问题分析与解决
核心原因
INFORMATION_SCHEMA.PROFILING的数据是会话级的,且MySQL默认关闭会话的profiling功能。你在MySQL客户端能查到有效结果,是因为客户端会话里手动开启了profiling,但Java程序的数据库连接是全新会话,默认未开启该功能,导致PROFILING表中无有效查询记录,最终返回0.0或null。
另外你的Java代码存在一处小问题:使用PreparedStatement时,调用带sql参数的executeQuery(sql)会重新编译SQL,违背预编译的设计初衷,应调用无参的executeQuery()。
解决步骤
- 开启当前会话的profiling:获取数据库连接后,先执行
SET profiling = 1;开启性能分析。 - 执行目标查询:必须先运行你需要计时的SQL,否则
PROFILING中不会生成对应记录。 - 修正PreparedStatement调用:去掉
executeQuery()的sql参数。 - 查询并获取耗时:执行原SUM统计查询,即可拿到目标查询的耗时数据。
修正后的Java代码
try { // 获取数据库连接 Connection myCon2 = DriverManager.getConnection(URL, USER, PW); // 开启当前会话的profiling Statement stmt = myCon2.createStatement(); stmt.execute("SET profiling = 1;"); // 执行需要计时的目标查询(替换为你实际要测试的SQL) stmt.execute("SELECT * FROM your_target_table LIMIT 10;"); // 执行耗时统计查询 String sql = "SELECT SUM(Duration) FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID = (SELECT MAX(QUERY_ID) FROM INFORMATION_SCHEMA.PROFILING)"; PreparedStatement myStmt = myCon2.prepareStatement(sql); ResultSet rs = myStmt.executeQuery(); // 此处无需传入sql参数 while (rs.next()){ Double duration = rs.getDouble(1); if (!rs.wasNull()) { System.out.println("查询耗时:" + duration + " 秒"); } else { System.out.println("未查询到有效耗时数据"); } } // 关闭资源(实际开发建议用try-with-resources自动关闭) rs.close(); myStmt.close(); stmt.close(); myCon2.close(); } catch (SQLException e) { e.printStackTrace(); }
额外说明
PROFILING表中Duration的单位是秒,如需毫秒可乘以1000转换。- 若需全局开启profiling,可在MySQL配置文件中设置
profiling=1,但不建议生产环境全局开启,会额外消耗性能。 INFORMATION_SCHEMA.PROFILING仅在MySQL 5.7及以上版本可用,低版本需更换性能统计方式。
内容的提问来源于stack exchange,提问作者Matthew Williams
相关产品推荐
相关产品推荐

