2011-02-22 46 views
2

我做了使用比時間戳大的類的所有版本的查詢:forRevisionsOfEntity緩慢

AuditReaderFactory 
    .get(emf.createEntityManager()) 
    .createQuery().forRevisionsOfEntity(clazz, false, true) 
    .add(AuditEntity.revisionProperty("timestamp").gt(existingIndex.lastModified())) 
    .getResultList(); 

這可以通過查詢再造一個@ManyToOne引用的對象:

select <audit cols for this type> 
from <audit table> 
where DTYPE IN (<class type>) 
and REV=(
    SELECT max(REV) 
    FROM <audit table> 
    where TYPE IN (<class type>) 
    and REV <= <maximum revision in revision entity table> 
    and <subquery>.id=<query>.id 
) 
and REVTYPE<>2 
AND <audit table>.id=<id of entity being restored> 

這個查詢速度非常慢,僅僅爲一個實體花了超過100分鐘(實際上,因爲我正在寫它,它仍然會繼續)。爲什麼它獲得實體的最後修訂(減去DEL修訂版)?使用ORDER BY REV LIMIT 1(或不具有LIMIT的數據庫)的速度要快得多。我幾乎想要直接去SQL,因爲這太慢了。它也可以通過直接在子查詢中使用id而不是引用查詢的表id來加快速度。我有索引DTYPE,REVREVTYPE,以及唯一的密鑰ID,REV因此它不是一個索引問題。

我不確定爲什麼它使用上面的查詢來重新創建引用的對象,並會感謝任何見解。這是在Pentium 4機器上的MySQL 5.1數據庫上,但是在雙核機器上也需要相當長的時間。

回答

1

在3.6.0版本的hibernate中,性能得到了顯着提升。你應該做的是使用ValidityAuditStrategy。添加到您的persistence.xml:

<property name="org.hibernate.envers.audit_strategy" 
       value="org.hibernate.envers.strategy.ValidityAuditStrategy"/> 

這將REVEND列添加到所以沒有選擇內需要您的審計表。閱讀更多here