我有一个包含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倍?如何在不增加堆空间的情况下处理这个问题?
答案 0 :(得分:1)
对于大约:focus
3_300_000
个对象,您将绕过Register
仅针对这些对象的2个标题(注册本身,长,日期)和RegisterType);甚至没有谈论他们的内部 - 这已经超过postgres报告;所以是的,你将使用相当多的堆空间。
看起来Hibernate出于某种原因将这些条目放在160MB
中,这意味着它将某些实例包含在Map
或LinkedNode
中,其中包含TreeNode
和Key
,至少更多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个(让我们说)对象吗?