java - SQL 在 Tomcat Servlet 中的执行时间比在普通 Java 程序中慢得多

标签 java performance tomcat6 ojdbc

然而,由于莫名其妙的原因,今天早上,我的两个过去很慢的查询的性能有所提高。我不知道为什么。
我对服务器没有权限,也许有人改变了什么。
问题没有了

简而言之:

  • 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)。

参见 Statement.setFetchSize .

关于java - SQL 在 Tomcat Servlet 中的执行时间比在普通 Java 程序中慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30775287/

相关文章:

mysql - 为什么 MySQL 不计算该列?我怎样才能重写我的查询以使其实现?

android - Android中如何处理非常非常大的数据?

tomcat - 如何配置 tomcat 以使用多个应用程序,其中一个是后备应用程序?

java - ClassNotFoundException 错误,即使 jar 文件存在于 WEB-INF/lib 目录中

Java 8 流式重构 - List<ObjA> 到 Map<String, List<ObjB>>

java - org.hibernate.hql.ast.QuerySyntaxException : unexpected token:

java - java中数组的部分复制

java - 确定最后一位上车的乘客! - 满足时间复杂性

Grails + Tomcat6 + 多个实例 + 共享库文件夹

java - 我如何告诉 KafkaAvroSerializer 与架构注册表的连接必须通过代理?