15

我检测到 Oracle 上的休眠和本机查询存在性能问题。当我在 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(); 

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

我意识到,如果我直接在本机查询上替换参数,然后使用 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

4

3 回答 3

7

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

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()用一些参数元数据调用的。我认为这个元数据还不够

于 2013-01-12T16:05:57.687 回答
0

我给你的答案是:

删除所有绑定参数并使用 StatelessSession 而不是 Session

使用 SQLQuery 而不是使用包含参数值的完整 SQL 进行查询

StatelessSession session = sessionFactory.openStatelessSession();

我有类似的问题,直到我得到更好的解决方案,这就是我设法使它工作的原因。请参阅 Hibernate 参数化 sql 查询慢速和活动 oracle 会话

于 2015-09-15T22:39:35.967 回答
0

<property name = "hibernate.temp.use_jdbc_metadata_defaults">false</property>

将此添加到您的 hibernate.cfg.xml 或更新您的应用程序属性文件。

于 2020-07-11T16:22:53.563 回答