2012-04-09 51 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