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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:57:28  来源:igfitidea点击:

How can i resolve the N+1 Selects problem?

javahibernatejpa

提问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:

更新:以下是一些示例: