我有使用Hibernate(通过JPA)的长期(但很简单)申请。 它正经历的是dramatic的衰退。 我可以缩小到要求打电话<代码>entityManager.clear()。 当Hibernate实体经理跟踪100 000个实体时,其跟踪速度比仅跟踪少数实体的速度要低约100x(见下文结果)。
! 最新信息:我已能够将这一标准缩小到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的使用显然以《自由守则》为主。