hibernate用join-fetch分配大量内存

lqfhib0f  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(264)

我试图提高应用程序的性能,所以我们做的第一件事就是查看数据库查询以优化它们。
我们所做的一件事是在适当的地方添加“join fetch”和“left join fetch”,以删除n+1查询。
另一个是批量检索结果( select distinct stuff from stuff left join fetch other_stuff where id in (?1) )而不是for循环逐个检索结果( for (id: ids) select distinct stuff from stuff left join fetch other_stuff where id = ?1 ).
问题是,虽然我们的查询速度快得多,数据库负载也低得多,但hibernate似乎需要更多的内存来实现这一点。
在分析应用程序时,我可以看到每秒分配的对象数超过了500000。垃圾收集器跟不上,应用程序冻结,最终导致内存不足。
从hprof来看,大多数对象似乎是在hibernate类中分配的。最严重的罪犯似乎是大部分人 select where id in (?1) . 它每秒执行一次,检索大约500个对象,但似乎负责每秒大约30万个对象的分配。
我的猜测是,由于连接,数据库返回300000多行(这确实是我手动运行时得到的结果) select count(*) from stuff join other_stuff ),hibernate必须在整合最后500个对象之前进行分配。
我说得对吗?
我想我不会做的 left join fetch 让hibernate用一个单独的查询来加载它们会大大减少这种分配,但会影响性能。
有没有一种方法可以减少内存分配,同时仍然可以立即获取数据?
谢谢

kiz8lqtg

kiz8lqtg1#

在hibernate中有3种不同的获取策略可供使用,不过在查询中只能指定连接获取。其他的只是注解,并在延迟加载期间生效。 JOIN 获取sql连接,这可能会导致n*m结果集爆炸,如您所想 SUBSELECT 通过嵌入主查询为关联执行一个查询 SELECT (默认)为主查询中的每n个元素发出一个select by id查询,其中n是配置的批大小。如果主查询非常复杂,因此 SUBSELECT 不合适。建议将批处理大小与通常在主查询中预期的元素数量对齐,以避免执行太多查询。
通常,我建议 SUBSELECT 获取,除非查询花费的时间太长或者可以估计主查询生成的元素数量。
其他性能改进可以通过减少select项的数量来实现,但这需要创建自定义dto模型。
我认为这是blaze持久性实体视图的完美用例。
我创建了这个库,以便在jpa模型和自定义接口或抽象类定义的模型之间进行简单的Map,比如spring数据在steroids上的投影。其思想是以您喜欢的方式定义目标结构(域模型),并通过jpql表达式将属性(getter)Map到实体模型。
对于blaze持久性实体视图,示例dto模型可以如下所示:

@EntityView(User.class)
public interface UserDto {
    @IdMapping
    Long getId();
    String getName();
    Set<RoleDto> getRoles();

    @EntityView(Role.class)
    interface RoleDto {
        @IdMapping
        Long getId();
        String getName();
    }
}

查询是将实体视图应用于查询的问题,最简单的就是按id进行查询。 UserDto a = entityViewManager.find(entityManager, UserDto.class, id); spring数据集成允许您像spring数据投影一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_us/index.html#spring-数据特征
即使 User 或者 Role 实体包含更多的列,通过使用blaze持久性实体视图,只有实际需要的数据才会被获取。
blaze持久性实体视图具有类似于hibernate的获取策略,还有另一个称为 MULTISET ,这是其中最好的。它将利用dbms端的json或字符串聚合函数将连接展平到单个列中。这避免了n*m结果集的爆炸,同时仍然在单个查询中执行。以下是有关获取策略的文档:https://persistence.blazebit.com/documentation/entity-view/manual/en_us/#anchor-获取策略

相关问题