Hibernate内存不足以查询128MB

时间:2017-04-12 17:34:31

标签: java mysql hibernate out-of-memory heap

我有一个包含3,244,977个寄存器和154.70 MB大小的表(来自phpmyadmin的数据)

我正在运行一个独立的java应用程序并尝试通过hibernate加载所有这些数据。我的域名是:

@Entity
public class Register {

    @Id
    @Column(nullable = false, unique = true, updatable = false)
    private Long userId;

    private Date checked;

    @Column(nullable = false)
    private RegisterType tipo;

    private boolean preLiked = false;
    private boolean preCommented = false;

}

其中RegisterType是hibernate在int中转换的枚举。

因为您可以看到我的域类并不复杂,考虑到java会为数据库中存储的数据大小增加一些开销,我将堆空间设置为4GB并运行我的应用程序:

java -Xmx4G -cp '....classpath.....' com.tomatechines.bot.Starter

因此,即使对象大10倍,它也应该适合堆。

但是我得到java.lang.OutOfMemoryError:Java堆空间

我担心这是其他负载与大量的数据,然后我做了一个测试...创建一个独立的jar,只是尝试加载该表中的所有数据,没有任何其他变量...但我'我仍然得到例外。

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.util.HashMap.resize(HashMap.java:703)
        at java.util.HashMap.putVal(HashMap.java:662)
        at java.util.HashMap.put(HashMap.java:611)
        at org.hibernate.internal.util.collections.IdentityMap.put(IdentityMap.java:94)
        at org.hibernate.engine.internal.StatefulPersistenceContext.addCollection(StatefulPersistenceContext.java:846)
        at org.hibernate.engine.internal.StatefulPersistenceContext.addUninitializedCollection(StatefulPersistenceContext.java:817)
        at org.hibernate.type.CollectionType.getCollection(CollectionType.java:739)
        at org.hibernate.type.CollectionType.resolveKey(CollectionType.java:436)
        at org.hibernate.type.CollectionType.resolve(CollectionType.java:429)
        at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:151)
        at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:125)
        at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1132)
        at org.hibernate.loader.Loader.processResultSet(Loader.java:992)
        at org.hibernate.loader.Loader.doQuery(Loader.java:930)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336)
        at org.hibernate.loader.Loader.doList(Loader.java:2610)
        at org.hibernate.loader.Loader.doList(Loader.java:2593)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2422)
        at org.hibernate.loader.Loader.list(Loader.java:2417)
        at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:109)
        at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1787)
        at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:363)
        at com.tomatechines.utils.hibernate.GenericDAO.find(GenericDAO.java:183)

同样的查询在不到一秒的时间内在phpmyadmin上运行。

在java中运行时它应该变大吗? hibernate使事情在数据库中增长到正常大小的30倍?如何在不增加堆空间的情况下处理这个问题?

3 个答案:

答案 0 :(得分:1)

对于大约:focus 3_300_000个对象,您将绕过Register 仅针对这些对象的2个标题(注册本身,长,日期)和RegisterType);甚至没有谈论他们的内部 - 这已经超过postgres报告;所以是的,你将使用相当多的堆空间。

看起来Hibernate出于某种原因将这些条目放在160MB中,这意味着它将某些实例包含在MapLinkedNode中,其中包含TreeNodeKey至少更多Value仅用于标题等等...

例如,您可以通过160MB衡量每个对象完全的数量;但这不会给你任何东西 - 你仍然会失败jol。我首先考虑为什么我需要首先在内存中接近350万个条目;如果有一个令人信服的理由我会尝试用更低的Hibernate。

答案 1 :(得分:0)

您可以像这样增加堆大小:https://stackoverflow.com/a/6452812/3978990

或者按部分从数据库和流程数据中分页数据。

答案 2 :(得分:0)

  

我正在运行一个独立的java应用程序并尝试通过hibernate加载所有这些数据......但是我得到了java.lang.OutOfMemoryError:Java堆空间

是否预期这取决于Register课程的详细信息。您正在使用休眠加载300万个Register对象。对于您正在加载的userId Long中的每一个long(它应该是nullable = false原始的,因为它是RegisterType)和checked字段所以那是另外600万件物品。我不确定@Transient是否也在数据库中 - 您可能需要说Register或其他东西也没有加载它。如果已加载,那么每个RegisterType会有另一个对象。我也不确定 curl --get --include 'https://doodle-manga- scraper.p.mashape.com/mangafox.me/manga/naruto/1' \ -H 'X-Mashape-Key: LhdkCyyF6Tmsh3BXTnN79quTbg08p1j2B20jsn89wOXridOzNe' \ -H 'Accept: text/plain' 字段是否会被热切地加载,这将是更多的对象。

因此,根据字段的不同,您可以在内存中讨论6到15,000多个对象,而且休眠时会有很多开销。它试图将对象添加到内部身份映射中,这是其缓存的一部分。你需要的内存肯定超过128mb。

最大的问题是,您是否确实需要内存中的所有数据来进行处理。你可以翻页数据库,所以一次只加载1000个(让我们说)对象吗?