Hibernate关联查询N+1查询问题记录
一、问题起因:线上某个列表的查询效率低下,需要定位下具体原因
二、定位过程:
1、因为问题出现之前有增加一个需求,查询会对表中某个json字段进行过滤,所以第一时间怀疑是数据量大了以后这种json内容筛选导致的,但测试后发现其影响关系不大,效率依然低。
2、转而怀疑是列表查询关联了一张子表导致,分析查看log日志后,发现一个之前没注意到的情况,一次查询竟然打印了很多条查询sql日志,这才看到Hibernate关联查询时,是先查询主表,拿到关联主键后,对每个子表单独请求一次数据库的,导致查询效率极其低下。
三、解决方案:
对于级联字段上添加注解,@BatchSize(size = n),其中n代表列表的返回条数。
一、@BatchSize
的实际行为
1、动态批量查询
如果主表返回 10条数据,Hibernate 会生成类似以下SQL一次性加载这10条对应的子表数据:
SELECT * FROM sub_table WHERE main_id IN (1, 2, 3, ..., 10);
如果主表返回 15条数据(size=20
),则同样执行一次 IN (1, 2, ..., 15)
查询。
2、不足size
时的处理
-
size
只是 批量加载的上限值,并非必须凑满。 -
Hibernate 会根据实际需要加载的主表ID数量动态生成SQL,不会补空值或报错。