Hibernate 6与Hibernate 5连接继承查询性能对比及配置咨询
Hibernate 6升级后关联查询性能下降的解决办法
问题场景
实体模型如下:
class Article { @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) public Set<UserPropertyValue<?>> getUserPropertyValues() { return userPropertyValues; } } @Entity @Inheritance(strategy = InheritanceType.JOINED) public abstract class UserPropertyValue<T> { } @Entity public class IntegerUserPropertyValue extends UserPropertyValue<Integer> { } @Entity public class StringUserPropertyValue extends UserPropertyValue<String> { } // 另有约10个类似子类,此处省略
调用article.getUserPropertyValues()时,Hibernate 5生成的PostgreSQL查询(简化后)为:
select long_list_of_fields from Article_UserPropertyValue userproper0_ inner join UserPropertyValue userproper1_ on userproper0_.userPropertyValues_id = userproper1_.id left outer join IntegerUserPropertyValue userproper1_2_ on userproper1_.id = userproper1_2_.id left outer join StringUserPropertyValue userproper1_10_ on userproper1_.id = userproper1_10_.id where userproper0_.Article_id = ?
该查询在200万条UserPropertyValue记录的库中耗时50ms,使用索引扫描。
升级到Hibernate 6后,生成的查询变为:
select long_list_of_fields from Article_UserPropertyValue upv1_0 join ( UserPropertyValue upv1_1 left join IntegerUserPropertyValue upv1_3 on upv1_1.id = upv1_3.id left join StringUserPropertyValue upv1_11 on upv1_1.id = upv1_11.id ) on upv1_1.id = upv1_0.userPropertyValues_id where upv1_0.Article_id = ?
Hibernate改用子查询包装继承类的连接逻辑,导致PostgreSQL优化器对UserPropertyValue表执行全表扫描,性能下降。
解决方案
可以通过设置Hibernate配置项,恢复到Hibernate 5的查询生成行为:
- 在
persistence.xml中添加:<property name="hibernate.query.subquery_inheritance_polymorphism" value="false"/> - 或者在Spring Boot的
application.properties中添加:spring.jpa.properties.hibernate.query.subquery_inheritance_polymorphism=false
该配置会禁用Hibernate 6默认的子查询式多态继承查询逻辑,回到直接关联所有子表的生成方式,让PostgreSQL优化器可以继续使用索引扫描,恢复之前的性能。
内容的提问来源于stack exchange,提问作者Alexander Malfait
相关产品推荐
相关产品推荐

