我们有一个在生产环境中运行的 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 container OC4J (whitin Oracle Application Server), Oracle Database 10.1.0.4, JDBC Driver for JDK 1.2 and 1.3, Hibernate version 3.2.6.ga, connection池库 C3P0 版本 0.9.1。
更新:感谢@BalusC 澄清确实是 Hibernate 执行了查询,现在我对发生的事情有了更好的了解。我将解释我们处理休眠会话的方式(这是非常基本的,是的,如果您有关于如何更好地处理它的建议,我们非常欢迎!)
我们有一个过滤器(实现 javax.servlet.Filter),它在启动时(init 方法)构造会话工厂(可能这只发生一次)。然后进入应用程序的每个 HttpRequest 都会通过过滤器并获得一个新会话并启动一个事务。当进程结束时,它通过过滤器返回,提交事务,终止休眠会话,然后继续前进页面(我们不将休眠会话存储在 Http 会话中,因为它在我们的测试)。
现在到了我认为问题所在的部分。在我们的开发环境中,我们在 Tomcat 5.5 中部署我们的应用程序,当我们启动服务时,所有过滤器都会立即启动,并且只启动一次。在使用 OC4J 的生产环境中似乎不是这样工作的。我们部署应用程序,只有当第一个请求到达时,OC4J 才会实例化过滤器。
这使我认为 OC4J 在每个请求上实例化过滤器(或至少多次,这仍然是错误的),从而在每个请求上创建一个会话工厂,执行该 %&%#%$# 查询,这导致我的问题!
现在,这是正确的吗?有没有办法让我配置 OC4J 让它只实例化一次过滤器?
非常感谢大家抽出时间来回复这个问题!