我必须处理分布在 20 个表上的大量数据(总计约 500 万条记录),我需要高效地加载它们。
我正在使用 Wildfly 14 和 JPA/Hibernate。
因为最后,每条记录都会被业务逻辑使用(在同一个事务中),我决定通过简单的方式将所需表的全部内容预加载到内存中:
em.createQuery("SELECT e FROM Entity e").size();
在那之后,每个对象都应该在交易中可用,因此可以通过:
em.find(Entity.class, id);
但这在某种程度上不起作用,仍然有很多对数据库的调用,尤其是对于关系。
如何有效地加载所需表格的全部内容,包括 关系并确保我得到了一切/不会有进一步的数据库调用?
我已经尝试过的:
- FetchMode.EAGER:仍然有太多单选/对象图太复杂
- EntityGraphs:与 FetchMode.EAGER 相同
- Join fetch 语句:迄今为止最好的结果,因为它同时填充了与被引用实体的关系
- 2 级/查询缓存: 不工作,可能与
em.find
的问题相同
需要注意的一件事是数据是不可变的(至少在特定时间是这样)并且也可以用于其他交易。
编辑:
我的计划是在 @Singleton
bean 中加载和管理整个数据。但我想确保我以最有效的方式加载它,并确保加载了整个数据。当业务逻辑正在使用数据时,应该不需要进一步的查询。在特定时间(ejb 计时器)之后,我将丢弃整个数据并从数据库重新加载当前状态(总是整个表)。
最佳答案
请记住,您可能需要 64 位 JVM 和大量内存。看看Hibernate 2nd Level Cache .由于我们没有您的代码,因此需要检查一些事项:
@Cacheable
注释将提示 Hibernate,以便实体可缓存- 配置二级缓存以使用类似 ehcache 的东西,并将最大内存元素设置为足够大以适合您的工作集
- 确保您没有在代码中不小心使用多个 session 。
如果您需要以这种方式处理事情,您可能需要考虑更改您的设计以不依赖于将所有内容都存储在内存中、不使用 Hibernate/JPA 或不使用应用程序服务器。这将使您更好地控制事情的执行方式。这甚至可能更适合 Hadoop 之类的东西。没有更多信息,很难说哪个方向最适合您。
关于java - 使用 JPA 将包括关系在内的整个表加载到内存中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53044327/