然而,由于莫名其妙的原因,今天早上,我的两个过去很慢的查询的性能有所提高。我不知道为什么。
我对服务器没有权限,也许有人改变了什么。
问题没有了。
简而言之:
- s.executeQuery(sql) 在服务器上的 tomcat servlet 中运行极其缓慢
- 相同的查询在同一台机器上没有 servlet(简单的 java 程序)也能正常运行
- 并非所有查询在 servlet 中都很慢。只有几个大一点的
- 同一个 servlet 在另一台机器上运行速度很快
更新
请阅读正文下方的更新内容!
我有一个 servlet
执行 SQL 请求并通过 JSON 发回结果。出于某种原因,某些请求需要花费大量时间来执行,但当我在任何 Oracle SQL 客户端中运行它们时,它们会立即执行。
我说的是相同 SQL 的 1 秒与 5 分钟的差异(这并不复杂)。
这怎么解释? 有没有办法提高基于 Java 的 SQL 请求的性能?
我正在使用传统的方式执行查询:
java.sql.Connection conn = null;
java.sql.Statement s = null;
ResultSet rs = null;
String dbDriver = "oracle.jdbc.driver.OracleDriver";
String dbConnectionString = "jdbc:oracle:thin:@" + dbHost + ":" + dbPort + ":" + dbSid;
Class.forName(dbDriver).newInstance();
conn = DriverManager.getConnection(dbConnectionString, dbUser, dbPass);
s = conn.createStatement();
s.setQueryTimeout(9999);
rs = s.executeQuery(newStatement);
ResultSetMetaData rsmd = rs.getMetaData();
// Get the results
while (rs.next()) {
// collect the results
}
// close connections
我试过 ojdbc14 和 ojdbc6,但没有区别。
更新 1: 我在客户端计算机上的本地 Java 项目(不是 servlet)中尝试了相同的 SQL,我立即得到了结果。所以我假设问题出在我的 servlet 或 tomcat 配置上?
更新 2: 罪魁祸首确实是 rs = s.executeQuery(mySql);我尝试改用 preparedStatement,但没有区别。
更新 3: 我创建了一个在本地 Tomcat 上运行的新 Servlet,查询很快返回。因此,问题来 self 的生产服务器或 Tomcat 配置。知道什么配置项会影响这个吗?
更新 4: 我在一个普通的 java 程序而不是一个 servlet(仍在同一台服务器上)中尝试了相同的代码,结果很快。因此,问题来自 Servlet 本身(或 Tomcat?)。仍然不知道该怎么做,但我缩小了范围:)
更新 5: Jstack 显示以下内容(它从我的 servlet 所在的位置开始,其余部分我删掉了)
"http-8080-3" daemon prio=3 tid=0x00eabc00 nid=0x2e runnable [0xaa9ee000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Packet.java:311)
at oracle.net.ns.DataPacket.receive(DataPacket.java:105)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:305)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:249)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:171)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:89)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:123)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:79)
at oracle.jdbc.driver.T4CMAREngineStream.unmarshalUB1(T4CMAREngineStream.java:429)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:397)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:30)
at oracle.jdbc.driver.T4CStatement.executeForDescribe(T4CStatement.java:762)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:925)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1104)
at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1309)
- locked <0xe7198808> (a oracle.jdbc.driver.T4CConnection)
at oracle.jdbc.driver.OracleStatementWrapper.executeQuery(OracleStatementWrapper.java:422)
所以我卡在 java.net.SocketInputStream.socketRead0(Native Method)
了?
最佳答案
在某些情况下(不确定这是否适用于您的情况)在 Statement
对象上设置 fetchSize
会产生很大的性能改进。这取决于正在获取的结果集的大小。
尝试将其设置为大于 Oracle 的默认值 10(请参阅 this link)。
关于java - SQL 在 Tomcat Servlet 中的执行时间比在普通 Java 程序中慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30775287/