我正在尝试以旧方式转换执行SQL查询的旧应用程序,如下所示:
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。
感谢。
答案 0 :(得分: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查询只是一个简单的查询(简单的Statement)。另一方面,HQL 中有一个参数 - 因此它将转换为JDBC PreparedStatement,并且为此编译SQL以便在多次调用它时可以快速运行它,并传递不同的变量值。
如果多次执行,您可能会发现HQL查询的平均速度比简单的JDBC查询快。
如果你只执行一次,那么简单的JDBC版本可能会比HQL更快,因为HQL最初会被编译。
这里有关于Statement vs PreparedStatement的一些有趣信息:
http://oreilly.com/catalog/jorajdbc/chapter/ch19.html
声明与PreparedStatement
人们普遍认为使用PreparedStatement对象是 比使用Statement对象更快。毕竟,准备好的声明 必须只针对数据库验证其元数据一次,而a 声明必须每次都这样做。那怎么可能是其他方式呢? 嗯,事情的真相是它需要大约65次迭代 在执行总时间之前准备好的声明赶上了 一份声明。这对您的性能有影响 应用程序,以及探索这些问题是本节的全部内容 约。
当谈到哪个SQL语句对象在下面表现得更好 典型的用法,陈述或准备好的陈述,事实就是这样 Statement对象产生最佳性能。当你考虑如何 SQL语句通常用于应用程序 - 1或2, 可能每次交易10-20(很少) - 你意识到a Statement对象将在比a更短的时间内执行它们 PreparedStatement对象。
答案 1 :(得分:1)
您可以使用session.createCriteria
以避免解析HQL并构建SQL。
尽管如此,对于复杂的查询,只比在第一次打击时支付一些小的惩罚(尽管它不可能是~100ms),而不是构建复杂的createCriteria
结构。
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html