2012-04-09 49 views
0

我想转换执行SQL的旧应用程序查询,如下的老路上:Hibernate的HQL的createQuery

java.sql.Connection connection = .... 
String queryStr="select acct from Person where acct in (select acct from Document where dbcreate_date > DATEADD(hh,-12, GETDATE())) and status not in ('A','P')"; 
... 
... 
java.sql.Statement statement = connection.createStatement(
       ResultSet.TYPE_SCROLL_INSENSITIVE, 
       ResultSet.CONCUR_READ_ONLY); 
     rs = statement.executeQuery(queryStr); 

上面的代码需要大约10毫秒。这包括获取数据库连接,创建语句并执行查询。

我现在使用Hibenate HQL并创建了一个HQL这样的查询:

Query query = session.createQuery("select p.acct from Person p where p.acct in (select acct from Document d where create_date > :date and status not in ('A','P'))"); 

现在只是这种说法“session.createQuery(......)”走约105毫秒,这大约是如上所述,以旧方式完成整个查询内容的时间再延长10倍。

现在我不太确定Hibernate查询缓存是如何工作的,但是如果我第二次运行这个相同的HQL语句,它将需要大约5毫秒。

现在我的问题是为什么使用Hibernate HQL发生这种行为?任何人都知道“session.createQuery(...)”方法里面发生了什么,第一次需要更长的时间,但第二次运行的时间要少得多? 我也注意到,Hibernate在执行“query.list()”时都会对数据库执行SQL。

谢谢。

回答

2

尝试在Hibernate中使用本机查询来比较性能:

Query query = session.createSQLQuery("select acct from Person where acct in (select acct from Document where dbcreate_date > DATEADD(hh,-12, GETDATE())) and status not in ('A','P')"); 

在性能:

你是不是真的比较喜欢一个像你的两个查询。

你的第一个例子,直接JDBC查询只是一个简单的查询(普通语句)。另一方面,HQL在中有一个参数 - 这样就可以转换成JDBC PreparedStatement,并且为此编译的SQL只编译一次,这样如果多次调用它,就可以快速运行它,并传递不同的结果变量值。

如果你多次执行,你可能会发现HQL查询的平均速度比简单的JDBC查询快。

如果您只执行一次,那么简单的JDBC版本可能会比HQL更快,因为HQL将在最初编译。

有VS的PreparedStatement这里声明了一些有趣的信息:

http://oreilly.com/catalog/jorajdbc/chapter/ch19.html

声明对战的PreparedStatement

有一种流行的看法,使用PreparedStatement对象比使用Statement对象更快 。毕竟,准备好的语句 必须仅针对数据库验证其元数据一次,而 语句必须每次都执行。那么它怎么可能是其他方式呢? 嗯,事情的真相是,它需要大约65次迭代的 准备好的语句,然后它的总执行时间才会通过语句达到 。这对您的 应用程序具有性能影响,并且探索这些问题是本节全部是 。

说到哪个SQL语句对象在 的典型用法,Statement或PreparedStatement下执行得更好,事实是Statement对象产生最佳性能。当您考虑如何在应用程序中通常使用SQL语句(这里为1或2)时,您可能会认为 Statement对象的执行时间会少于PreparedStatement的 目的。

+0

是的它是有道理的。我是Hibernate缓存的新手,但我开始明白它的好处以及如何正确使用它。感谢您的回答。 – Marquinio 2012-04-10 01:21:37