forRevisionsOfEntity很慢

时间:2011-02-22 22:26:11

标签: java hibernate hibernate-envers

我正在使用以下内容查询大于时间戳的类的所有修订:

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来加速它。我有DTYPEREVREVTYPE上的索引,以及id REV上的唯一键,因此它不是索引问题。

我不确定为什么它使用上面的查询来重新创建引用的对象,并且会欣赏任何洞察力。这是在奔腾4机器上的MySQL 5.1数据库上,但在双核机器上也需要相当长的时间。

1 个答案:

答案 0 :(得分:1)

在3.6.0版本的hibernate中,性能得到了显着提升。你应该做的是使用ValidityAuditStrategy。将其添加到persistence.xml:

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

这会将REVEND列添加到您的审计表中,因此不需要内部选择。阅读更多here