0

我正在尝试以旧方式转换执行 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。

谢谢。

4

2 回答 2

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')");

关于性能:

您并没有真正将 like 与 like 与您的两个查询进行比较。

您的第一个示例,直接 JDBC 查询只是一个简单的查询(plain Statement)。另一方面,HQL 在其中有一个参数- 因此它将转换为 JDBC PreparedStatement,并且此 SQL 被编译一次,以便您可以在多次调用它时快速运行它,并传递不同的变量值.

如果您多次执行这两项操作,您可能会发现 HQL 查询平均比简单的 JDBC 查询要快。

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

这里有一些关于 Statement vs PreparedStatement 的有趣信息:

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

语句与 PreparedStatement

人们普遍认为使用 PreparedStatement 对象比使用 Statement 对象更快。毕竟,准备好的语句只需要根据数据库验证其元数据一次,而语句必须每次都进行。那么怎么可能是其他方式呢?好吧,事情的真相是,在它的总执行时间赶上一条语句之前,它需要大约 65 次准备好的语句迭代。这对您的应用程序有性能影响,探索这些问题就是本节的全部内容。

当谈到在典型使用下哪个 SQL 语句对象性能更好时,Statement 或 PreparedStatement,事实是 Statement 对象产生最佳性能。当您考虑在应用程序中通常如何使用 SQL 语句时(此处为 1 或 2 个,每个事务可能使用 10 到 20 个(很少更多)),您会意识到 Statement 对象将在比 PreparedStatement 对象更短的时间内执行它们。

于 2012-04-09T23:37:51.163 回答
1

您可以使用session.createCriteria以避免解析 HQL 和构建 SQL。

不过,对于复杂的查询,只需在第一次命中时支付一些小罚金(尽管不太可能是 ~100 毫秒),而不是构建复杂的createCriteria结构。

http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html

于 2012-04-09T21:31:12.550 回答