我正在處理一些性能問題,這些問題看起來與重複調用數據庫(幾千個對象,每個都有幾十個子對象)有關。Grails/hibernate Eager提交似乎被忽略
問題似乎是,儘管加載關係(並確認對象實際上是通過記錄hibernate SQL實際加載的),但它們仍然每次都從數據庫中獲取。
我的直覺是問我是否有辦法告訴grails/hibernate在內存中使用這個對象,而不是回到數據庫,因爲我肯定它已經在內存中了?
雖然這可能是錯誤的問題。
給出一個具體的例子。我的域類父定義:
static hasMany = [children: Child]
static mapping = {children fetch:'select'}
可能已經獲取:「渴望」 ......我想兩者兼得,不知道哪個產生下面的日誌結果,但它顯然急切地獲取數據。
我做的第一件事是:
高清結果= Parent.executeQuery(「從父p選擇不同的P其中......複雜的where子句」)
查看日誌,這不急切地加載孩子的關係,但這並不是非常意外,並且在這一點上並不是真正的殺手。接下來,我遍歷整個家長:
for(Parent parent : results)
{ blah blah }
循環的每次迭代顯示,Hibernate是根據ID查詢父p和似乎急切地加載所有子關係。日誌片段:
select
parent0_.id as id4_4_,
parent0_.version as version4_4_,
parent0_.date_created as date3_4_4_,
child1_.parent_id as parent6_6_,
child1_.id as id6_,
child1_.child_idx as idx9_6_,
child1_.id as id22_1_,
child1_.version as version22_1_,
...continues for all fields.
注意:我不知道爲什麼它將id字段映射兩次。
太棒了!它急切地加載我需要的子對象!在上面的父循環中,我然後迭代孩子:
for(Parent parent : results)
{
for(Child child : parent.children)
{ blah blah }
}
而這就是問題所在。在內部循環的每次迭代中,都會記錄另一個hibernate查詢,通過id加載對象。日誌片段:
select child0_.id as id22_1_,
child0_.version as version22_1_,
child0_.parent_id as parent6_22_1_,
child0_.sequence_number as sequence8_22_1_,
...and all the rest
這些不必要的負荷是絕對殺死我的表現(至少,這似乎是瓶頸,我不能100%確定),因爲它的執行數千讀取。非常感謝您對如何正確使用內存對象或不同方式加載數據的任何想法。
感謝您的建議,任何事情都值得一試,當你卡住了。 – Trebla 2012-08-15 12:31:08