我们有一个在生产环境中运行的 Web 应用程序,有时客户抱怨应用程序变得多么慢。
当我们检查应用程序和数据库的情况时,我们发现这个“宝贵”的查询正在由多个用户同时执行(从而对数据库服务器造成极高的负载):
SELECT NULL AS table_cat,
o.owner AS table_schem,
o.object_name AS table_name,
o.object_type AS table_type,
NULL AS remarks
FROM all_objects o
WHERE o.owner LIKE :1 ESCAPE :"SYS_B_0" AND
o.object_name LIKE :2 ESCAPE :"SYS_B_1" AND
o.object_type IN(:"SYS_B_2", :"SYS_B_3")
ORDER BY table_type, table_schem, table_name
我们的应用程序不执行这个查询,我相信它是一个 Hibernate 内部查询。我发现很少有关于 Hibernate 为什么执行这种极其繁重的查询的信息,因此非常感谢任何关于如何避免它的帮助!
生产环境信息:Red Hat Enterprise Linux 5.3(Tikanga)、JDK 1.5、Web 容器 OC4J(Oracle 应用服务器中)、Oracle Database 10.1.0.4、JDK 1.2 和 1.3 的 JDBC 驱动程序、Hibernate 版本 3.2.6.ga、连接池库 C3P0 版本 0.9.1。
UPDATE:感谢 @BalusC 的澄清,确实是 Hibernate 执行了查询,现在我对发生的事情有了更好的了解。我将解释我们处理休眠会话的方式(是的,这是非常基本的,如果您有关于如何更好地处理它的建议,我们非常欢迎!)
我们有一个过滤器(实现 javax.servlet.Filter),当它启动(init 方法)时,它会构造会话工厂(假设这只发生一次)。然后每个发送到应用程序的 HttpRequest 都会经过过滤器并获得一个new会话并启动一个事务。当过程结束时,它通过过滤器返回,提交事务,killshibernate 会话,然后继续前进页面(我们不将 hibernate 会话存储在 Http 会话中,因为它在我们的测试中从未正常工作)。
现在我认为问题所在的部分来了。在我们的开发环境中,我们在 Tomcat 5.5 中部署应用程序,当我们启动服务时,所有过滤器都会立即启动并只有一次。在 OC4J 的生产环境中似乎不是这样工作的。我们部署应用程序,并且仅当第一个请求到达时,OC4J 才会实例化过滤器。
这让我认为 OC4J 实例化了过滤器every请求(或至少多次,这仍然是错误的),从而在每个请求上创建一个会话工厂,它执行 %&%#%$# 查询,这导致了我的问题!
现在,这是正确的吗?有没有办法让我配置 OC4J 使其仅实例化过滤器一次?
非常感谢大家花时间回复此问题!