在使用相同的本机Oracle查询的TOAD时,Hibernate + Java的性能会降低但速度很快

Sob*_*ino 11 java oracle hibernate

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

我的SQL查询相当复杂,返回一个唯一值(因此,问题与实现类所需的时间无关),它包含几个参数格式为':nameParameter'.此查询存储在String中.例如,

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

当我在TOAD上执行句子时,它会在几毫秒内解决.但是用Hibernate这个句子

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

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

query.uniqueResult(); 
Run Code Online (Sandbox Code Playgroud)

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

我意识到如果我直接在原生查询中替换参数然后我使用Hibernate执行句子,时间会急剧减少.它会是这样的:

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

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

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");
query.uniqueResult(); 
Run Code Online (Sandbox Code Playgroud)

谁知道发生了什么?

提前致谢.

PS:Oracle版本是9i和Hibernate 3.2

ben*_*n75 6

我想这个代码发生了什么:

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");
query.setParameter(nameParameter1, value1);
query.setParameter(nameParameter2, value2);
query.uniqueResult(); 
Run Code Online (Sandbox Code Playgroud)

这是:

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

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

为什么?

看一下HibernateSessionImpl.createSQLQuery(...)我找到这行代码的源代码:

SQLQueryImpl query = new SQLQueryImpl(
                sql,
                        this,
                        factory.getQueryPlanCache().getSQLParameterMetadata( sql )
        );
Run Code Online (Sandbox Code Playgroud)

getQueryPlanCache()用一些parameterMetaData 调用.我认为这个元数据不够.