java 如何解决 N+1 Selects 问题?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2593029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can i resolve the N+1 Selects problem?
提问by Maxime ARNSTAMM
I have trouble understanding how to avoid the n+1 select in jpa or hibernate.
我无法理解如何避免 jpa 或 hibernate 中的 n+1 选择。
From what i read, there's the 'left join fetch', but i'm not sure if it still works with more than one list (oneToMany)..
从我读到的内容来看,有“左连接获取”,但我不确定它是否仍然适用于多个列表(oneToMany)。
Could someone explain it to me, or give me a link with a clear complete explanation please ?
有人可以向我解释一下,或者给我一个带有清晰完整解释的链接吗?
I'm sorry if this is a noob question, but i can't find a real clear article or doc on this issue.
如果这是一个菜鸟问题,我很抱歉,但我找不到关于这个问题的真正清晰的文章或文档。
Thanks
谢谢
回答by Péter T?r?k
Apart from the join, you can also use subselect(s). This results in 2 queries being executed (or in general m+ 1, if you have mlists), but it scales well for a large number of lists too, unlike join fetching.
除了连接之外,您还可以使用子选择。这会导致执行 2 个查询(或者通常为m+ 1,如果您有m 个列表),但与连接提取不同,它也可以很好地扩展大量列表。
With join fetching, if you fetch 2 tables (or lists) with your entity, you get a cartesian product, i.e. all combinations of pairs of rows from the two tables. If the tables are large, the result can be huge, e.g. if both tables have 1000 rows, the cartesian product contains 1 million rows!
使用连接提取,如果您使用实体提取 2 个表(或列表),您将获得笛卡尔积,即来自两个表的行对的所有组合。如果表很大,结果可能很大,例如,如果两个表都有 1000 行,则笛卡尔积包含 100 万行!
A better alternative for such cases is to use subselects. In this case, you would issue 2 selects - one for each table - on top of the main select (which loads the parent entity), so altogether you load 1 + 100 + 100 rows with 3 queries.
对于这种情况,更好的替代方法是使用子选择。在这种情况下,您将发出 2 个选择 - 每个表一个 - 在主选择(加载父实体)之上,因此您总共加载 1 + 100 + 100 行和 3 个查询。
For the record, the same with lazy loading would result in 201 separate selects, each loading a single row.
对于记录,与延迟加载相同将导致 201 个单独的选择,每个选择加载一行。
Update:here are some examples:
更新:以下是一些示例:
- a tutorial: Tuning Lazy Fetching, with a section on subselects towards the end (btw it also explains the n+1 selects problem and all strategies to deal with it),
- examples of HQL subqueriesfrom the Hibernate reference,
- just in case, the chapter on fetching strategiesfrom the Hibernate reference - similar content as the first one, but much more thorough
- 一个教程:调整延迟获取,最后有一个关于子选择的部分(顺便说一句,它还解释了 n+1 选择问题和所有处理它的策略),
- 来自 Hibernate 参考的 HQL 子查询示例,
- 以防万一,有关从 Hibernate 参考中获取策略的章节- 与第一个内容类似,但更彻底

