English 中文(简体)
排他性查询速度较慢,直到()明确。
原标题:Hibernate queries much slower with flushMode=AUTO until clear() is called

我有使用Hibernate(通过JPA)的长期(但很简单)申请。 它正经历的是dramatic的衰退。 我可以缩小到要求打电话<代码>entityManager.clear()。 当Hibernate实体经理跟踪100 000个实体时,其跟踪速度比仅跟踪少数实体的速度要低约100x(见下文结果)。 why 在追踪许多实体时,自愿放慢了这么多的速度? 是否有其他办法?


! 最新信息:我已能够将这一标准缩小到Hibernate的汽车膨胀代码。 !

具体到org.hibernate.event.internal.AbstractFlupingEventListener sflushEntities (meth (至少 in Hibernate 4.1.1.Final)。 在这种局面中,存在着一种循环,即从持续存在的角度来看待ALL实体,围绕每个实体进行大量检查(尽管所有实体已经用我的榜样抽调)。

因此,部分回答我的问题的第二部分,可以通过确定“滚动模式”来解决业绩问题。 FlushModeType.COMMIT on the query (见下文最新结果)。 e.g.

Place place = em.createQuery("from Place where name = :name", Place.class)
    .setParameter("name", name)
    .setFlushMode(FlushModeType.COMMIT)  // <-- yay!
    .getSingleResult();

......但是,这似乎只是简单地解决了在知道货物是否偏离了问答方法而不是将其留在更新方法上的责任。 这还在很大程度上意味着,我要么必须就所有查询方法向麻省理工学院确定流动模式,要么更可能地把它放在实体管理上。

这使我很想知道:这一预期行为吗? 我做了一些错误的 doing弄或我如何界定实体? 还是这种限制(或可能是ug)是自愿的?


我用来孤立问题的样本代码如下:

The Test Entity

@Entity @Table(name="place") @Immutable
public class Place {
    private Long _id;
    private String _name;

    @Id @GeneratedValue
    public Long getId() { return _id; }
    public void setId(Long id) { _id = id; }

    @Basic(optional=false) @Column(name="name", length=700,
        updatable=false, nullable=false, unique=true,
        columnDefinition="varchar(700) character set  ascii  not null")
    public String getName() { return _name; }
    public void setName(String name) { _name = name; }

    @Override
    public boolean equals(Object o) { /* ... */ }

    @Override
    public int hashCode() { return getName().hashCode(); }
}

The Benchmark Code

测试代码一生成了100 000个随机地名,并插入这些名称。 然后按姓名随机查询其中5000人。 名称栏有索引。

Place place = em.createQuery(
    "select p from Place p where p.name = :name", Place.class)
    .setParameter("name", name)
    .getSingleResult();

为了进行比较,并为了确保数据库中无一例外,我对单独随机选定的5000个地名进行了以下的JDBC查询(em.unwrap(Session.class.doWork(......):

PreparedStatement ps = c.prepareStatement(
    "select id, name from place where name = ?");
ps.setString(1, name);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
    Place place = new Place();
    place.setId(rs.getLong(1));
    place.setName(rs.getString(2));
}
rs.close();
ps.close();

(说明,我确实为基准上5 000个查询中的每一个查询制作和贴出一份发言稿)。

The Results

以下所有结果平均超过5,000个查询点。 收到了<代码>-Xmx1G。

Seconds/Query    Approach
0.000160s        JDBC
0.000286s        Hibernate calling clear() after import and every 100 queries
0.000653s        Hibernate calling clear() once after the import
0.012533s        Hibernate w/o calling clear() at all
0.000292s        Hibernate w/o calling clear(), and with flush-mode COMMIT

其他意见:在解放阶段的问询(不是任何明确电话)中,java进程把一个核心gged到接近100%的利用。 联合考试委员会从未超过500德国马克。 在询问期间,GC也开展了许多活动,但CPU的使用显然以《自由守则》为主。

问题回答

但主要是我很奇怪的是,为什么Hibernate似乎展示O(n)或甚至O(n^2)的眼光,这样它就能够利用一个老板或双手树,使问题迅速解决。 在跟踪100 000个实体与100个实体时,通知2级大鼠差异。

O(n2)复杂性是必须处理问题的。 由于Hibernate内部推迟更新,只要可以插入(利用机会将类似更新/改动合在一起,特别是如果你确定物体的多重性质的话)。

因此,在你能够安全地查询数据库中的物体之前,Hibernate必须探测到所有物体的变化和所有变化。 这里的问题是,藏匿国也有一些通知和拦截。 因此,它控制着持久性环境的每个实体的物体。 即便物体本身不易变,也可能持有 mu物体,甚至收集参考资料。

拦截机制还允许你接触被考虑为 d脏的任何物体,以便你自己的法典能够实施额外的 d脏检查,或进行额外计算,如计算数额、平均价值、记录额外信息等。

但请在一分钟内看一下该守则:

• 要求编写质询结果:

DefaultFlushEventListener.onFlush(..)
  -> AbstractFlushingEventListener.flushEverythingToExecution(event)
    -> AbstractFlushingEventListener.prepareEntityFlushes(..)

执行使用:

for ( Map.Entry me : IdentityMap.concurrentEntries( persistenceContext.getEntityEntries() ) ) {
        EntityEntry entry = (EntityEntry) me.getValue();
        Status status = entry.getStatus();
        if ( status == Status.MANAGED || status == Status.SAVING || status == Status.READ_ONLY ) {
            cascadeOnFlush( session, entry.getPersister(), me.getKey(), anything );
        }
    }

由于你能够看到一个所有实体在持续情况下的地图被检索和编辑。

这意味着,每当你在以前的所有结果中都会发出询问,以检查 d脏物体。 甚至连更多的中学 OnFlush制造了一个新目标,甚至更多。 这里是学院法典。 OnFlush:

private void cascadeOnFlush(EventSource session, EntityPersister persister, Object object, Object anything)
throws HibernateException {
    session.getPersistenceContext().incrementCascadeLevel();
    try {
        new Cascade( getCascadingAction(), Cascade.BEFORE_FLUSH, session )
        .cascade( persister, object, anything );
    }
    finally {
        session.getPersistenceContext().decrementCascadeLevel();
    }
}

So this is the explanation. Hibernate just checks every object managed by the persistence context every time you issue a query.

因此,在座各位来看,复杂的计算方法是:

  1. Query: 0 entities
  2. Query: 1 entity
  3. Query: 2 entities ..
  4. Query: 100 entities . .. 100k + 1 Query: 100k entries

因此,我们有O(0+1+2......+n)=O(n(n+1)/2)=O(n2)。

This explains your observation. In order to maintain a small cpu and memory footprint hibernate managed persistence context should be kept as small as possible. Letting Hibernate manage more than lets say 100 or 1000 entities slows down Hibernate considerably. Here one should consider to change the flush mode, use a second session for query and one for change (if this is possible at all) or use StatelessSession.

因此,你的意见是正确的,是O(n2)正在继续。

Perhaps you are familiar that EntityManager keeps track of persistent objects (i.e the ones created by calling em.createQuery(...).getSingleResult()). They accumulate in so called persistent context or session (the Hibernate term) and allows very neat features. For example you can modify the object by calling the mutator method setName(...) and the EntityManager will synchronize this state change in memory with database (will issue an UPDATE statement) whenever it is appropriate. This happens without requiring you to call explicit save() or update() methods. All you need is to work with the object as if it is normal Java object and EntityManager will take care of persistence.

www.un.org/spanish/ecosoc 为什么如此缓慢?

其中,它确保每个主要记忆中都有just one, 即。 这意味着,如果你把一行和两行相加,那么就只有一栏(两种结果都将是=)。 这具有许多意义——如果你有2份同一行文的复印件,EntityManager,那么就能够保证它能与你能够独立改变这两个物体的可靠同步。 或许还有很多其他低级业务,如果要追踪很多物体,则最终会放缓<代码>Entitymanager。 <代码>clear(> 方法实际上消除了当地对持久性环境的反对,使任务更加容易(除非物体可跟踪=更快操作)。

How can you get around it?

如果您的<代码>EntityManager 执行是Hibernate, 您可使用。 我认为,你可以通过:

StatelessSession session = ((Session) entitiesManager.getDelegate())。getSessionFactory ( openStatelessSession();

(NB) https://stackoverflow.com/a/5888/848569“question





相关问题
Multiple Hibernate instances using C3P0

I am facing a weird problem and it seems to be c3p0 related. I am starting two instances of an app in the same java vm which interact with each other. After some operations "APPARENT DEADLOCK" ...

Hibernate vs Ibatis caching

We can speed up a hibernate app easyly with 2nd level cache using infinispan or ehcache/terracotta,... but ibatis only have a simple interface to implement for caching. And hibernate knows more ...

Using annotations to implement a static join in hibernate

I m relatively new to hibernate and was wondering if someone could help me out. While I have no issues implementing a normal join on multiple columns in hibernate using the @JoinColumns tag, I m ...

Hibernate query with fetch question

I have a 2 entities in a One-To-Many relationship: OfficeView.java: public class OfficeView implements java.io.Serializable { private Integer officeId; private String addr1; private ...

hibernate interceptors : afterTransactionCompletion

I wrote a Hibernate interceptor : public class MyInterceptor extends EmptyInterceptor { private boolean isCanal=false; public boolean onSave(Object entity, Serializable arg1, Object[] arg2, String[]...

How to prevent JPA from rolling back transaction?

Methods invoked: 1. Struts Action 2. Service class method (annotated by @Transactional) 3. Xfire webservice call Everything including struts (DelegatingActionProxy) and transactions is configured ...

Hibernate/GORM: collection was not processed by flush()

I have an integration test in my Grails application that fails when I try to save an entity of type Member invitingMember.save(flush: true) This raises the following exception org.hibernate....

Hibernate Criteria API equivalent for "elements()"

Is it possible to implement the following query using Criteria API? select order from ORDER as order,ITEM as item where item.itemID like ITM_01 and item in elements(order.items)

热门标签