我在编写事务时遇到了JavaDB (Derby)的性能问题。每笔交易花费超过500毫秒,我一天可能有几十万。我希望在MySql上部署,我不知道我是否会遇到同样的问题,但是在尝试之前,我正在尝试改进Derby的性能。
一个事务涉及更新一串记录--多达6条,如下所示:
public void update(List<Tally> list) {
try {
utx.begin();
for (Tally tally : list) em.merge(tally);
utx.commit();
// etc我想看看更新查询是否能更好地工作,因为JPA不需要跟踪更新和组成SQL查询的列(附带的问题是:这是一个好的理论吗?)
因此,我编写了一个命名查询,如下所示:
@NamedQuery(name="TallyUpdate",
query="UPDATE Tally t SET t.vote = t.vote + 1 WHERE t.id IN :idSet"是这样操作的:
@PersistenceContext protected EntityManager em;
@Resource protected UserTransaction utx;
public void incrementVote(List<Long> idList) {
Query q = em.createNamedQuery("TallyUpdate");
q.setParameter("idSet", idList);
try {
utx.begin();
q.executeUpdate();
utx.commit();
//etcexecuteUpdate()调用总是抛出异常:
SEVERE: javax.persistence.TransactionRequiredException: executeUpdate is not supported for a Query object obtained through non-transactional access of a container-managed transactional EntityManager
at com.sun.enterprise.container.common.impl.QueryWrapper.executeUpdate(QueryWrapper.java:225)JPA的实现是EclipseLink 2.3.0
这个词-沙拉例外意味着什么,我应该如何运行更新?
结果公告:
我确实将createnamedQuery()调用移到了utx.begin()调用之后,并且更新开始工作。我不知道为什么,但我现在要带着它跑。
目前还没有关于相对表现的结果,但我上面的帖子是误导的。当对一次投票进行统计时,它有24到36种不同的方式,而不是6种。因此,对原始update()方法(使用merge())的调用有六个,每个调用的列表上都有大约6条记录。这个电话集合需要超过500毫秒。如果理货表是空的,那么基准值只有大约27 is,这就是我想要看到的速度。当表填充到50,000行或更多时,我看到的是500ms+号。
如果有人对我的结果感兴趣,请评论。
P.S.这是运行在GlassFish下的JSF应用程序,而不是EJB。我不知道这是否与业绩有关。
发布于 2011-11-05 19:28:33
由于您有一个容器管理的实体管理器,我猜您已经将这个东西注入到了EJB中。因为这意味着事务是由容器管理的,也就是说,您不需要在代码中明确地启动它们。默认情况下,事务在EJB方法启动时启动,当该方法完成时结束。这是针对无状态EJB的。对于状态EJB,事务可以跨越多个方法调用,并在EJB“破坏”方法被调用时结束。因此,您应该决定:要么使用容器管理的实体管理器(如这里所示,一个注入EJB ),然后让容器管理事务(通过JTA),要么使用应用程序管理的实体管理器,然后自己处理代码中的事务。
关于性能,Apache人员说Derby在生产、匹配方面非常好,有时甚至在某些情况下甚至超过MySQL和PostgreSQL,就像您在本Apache文档中看到的那样:
http://home.online.no/~olmsan/publications/pres/apachecon05us/apachecon05.pdf
就拿这一点来说,德比的表现并不是举世闻名的。甚至本文档也显示,在某些情况下,Derby比MySQL慢得多。此外,在Derby上CPU的使用也更大。
我的建议是:对MySQL进行概念验证,并在数据库上进行基准测试。如果这就是你要在生产中使用的东西,那么在不同的数据库上对你的应用程序进行性能调整是没有什么意义的。
https://stackoverflow.com/questions/8022453
复制相似问题