java - 在 Hibernate + Java 上性能较慢,但当我将 TOAD 与相同的 native Oracle 查询一起使用时性能很快

标签 java oracle hibernate

我检测到 Oracle 上的 hibernate 和 native 查询存在性能问题。当我在 TOAD 上执行带有多个参数的复杂 SQL 查询时,我得到了以毫秒为单位的结果。但是,当我使用 Hibernate 执行相同的查询时,这个时间会大幅增加(最多四秒甚至更多)。

我的 SQL 查询相当复杂,返回一个唯一值(因此,问题与安装类所需的时间无关)并且它包含几个格式为“:nameParameter”的参数。此查询存储在一个字符串中。例如,

String myNamedNativeQuery = "select count(*) from tables "+
                            "where column1 = :nameParameter1 "+ 
                            "and column2 = :nameParameter2";  
                            //actually my sentence is much more complex!!

当我在 TOAD 上执行句子时,它会在几毫秒内得到解决。但是将这句话与 Hibernate 一起使用

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");

query.setParameter(nameParameter1, value1);
query.setParameter(nameParameter2, value2);

query.uniqueResult(); 

需要几秒钟才能得到相同的结果。

我意识到,如果我直接在 native 查询上替换参数,然后使用 Hibernate 执行句子,时间会大大减少。应该是这样的:

String strQuery = session.getNamedQuery("myNamedNativeQuery").getQueryString();

myNamedNativeQuery = myNamedNativeQuery.replace("nameParameter1", value1);
myNamedNativeQuery = myNamedNativeQuery.replace("nameParameter2", value2);

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");
query.uniqueResult(); 

有人知道发生了什么吗?

提前致谢。

PS:Oracle版本是9i和Hibernate 3.2

最佳答案

我认为这段代码发生了什么:

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");
query.setParameter(nameParameter1, value1);
query.setParameter(nameParameter2, value2);
query.uniqueResult(); 

这是:

在第 1 行:根据命名参数的一些预期值创建查询计划。

在第 4 行:查询是用 value1 和 value2 执行的,但是这些值对于第 1 行详细说明的查询计划来说不是“好的值”,因此,数据库正在为实际值执行一个非常不合适的计划这需要很多时间。

为什么?

查看 HibernateSessionImpl.createSQLQuery(...) 的源代码,我发现了这行代码:

SQLQueryImpl query = new SQLQueryImpl(
                sql,
                        this,
                        factory.getQueryPlanCache().getSQLParameterMetadata( sql )
        );

用一些参数元数据调用 getQueryPlanCache()。我认为此元数据不够好

关于java - 在 Hibernate + Java 上性能较慢,但当我将 TOAD 与相同的 native Oracle 查询一起使用时性能很快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14294735/

相关文章:

java - 如何订购 Vaadin 表行?

Java - 计算最常见的元素

java - 删除空格并大写用户输入

java - jar 在 unix 和 linux 中的行为是否不同?

sql - Oracle:SQL 选择带时间戳的日期

oracle - 如何使用查询获取2个给定日期之间的月份列表?

oracle - 如何编写 oracle Query 将字符串拆分为按类别相关的多行

hibernate - 如何在运行时更改 hibernate 映射属性

java - 我缺少哪些 Hibernate 注释?

java - 如何为hibernate指定验证组