Hibernate 子选择与批量获取
Hibernate 提供(至少)两个选项来解决 N+1 查询问题。第一个是将 FetchMode 设置为 Subselect,这会生成一个带有 IN 子句的选择和此 IN 子句内的子选择。另一种是指定 BatchSize,它生成一个带有包含父 ID 的 IN 子句的选择。
两者都有效,但我发现“子选择”选项经常会遇到性能问题,因为对父项的查询很复杂。另一方面,如果 BatchSize 较大(例如 1000),则查询数量和这些查询的复杂性都非常小。
我的问题是:什么时候你会使用 Hibernate 的 Subselect FetchMode 而不是 BatchSize?如果您有大量父条目(数千),则 Subselect 可能有意义,但是是否有其他情况下您更喜欢 Subselect 而不是 BatchSize?
编辑:我注意到在处理急切加载时两者之间存在差异。如果您将 xToMany 关联设置为通过子选择急切加载,它会像惰性选择一样生成子选择。但是,如果指定 BatchSize,则生成的查询将使用外连接而不是单独的查询。有没有办法强制 Hibernate 在急切加载时使用单独的批处理查询?
Hibernate provides (at least) two options for getting around the N+1 query problem. The one is setting the FetchMode to Subselect, which generates a select with a IN-clause and a subselect within this IN-clause. The other is to specify a BatchSize, which generates a select with a IN-clause containing the parents' IDs.
Both work but I find that the Subselect option often runs into performance problems due to the query for the parents being complex. On the other hand, with a large BatchSize (say 1000), the number of queries and complexity of those queries are very small.
My question is thus: when would you use Hibernate's Subselect FetchMode over BatchSize? Subselect probably makes sense if you have a very large number of parent entries (thousands), but are there any other scenarios where you'd prefer a Subselect to BatchSize?
EDIT: I noticed a difference between the two when dealing with eager loading. If you have an xToMany association set to be loaded eagerly and through a subselect, it generates a subselect like it would if it was lazy. If you specify a BatchSize however, the generated query makes use of a outer join instead of a seperate query. Is there any way to force Hibernate to use a seperate batched query when loading eagerly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不使用子选择,因为它很难控制。在一个具有复杂业务逻辑和大型团队的大型系统中,很难说使用了哪些查询。子选择可能在您确切知道执行哪个查询的特定情况下起作用。
批量获取有一些很大的优点。它并不总是最快的,但通常足够快。另一方面它非常稳定,没有任何副作用并且对业务逻辑完全透明。我从不使用高于 100 的批处理值。将 N+1 减少到合理的查询量就足够了。
I don't use subselect, because it is hard to control. In a very large system which has complex business logic and a large team working on it, it is too hard to say which queries are used. Subselect may work in specific cases where you exactly know which query is performed.
Batch fetching has some big advantages. It is not always the fastest, but usually fast enough. On the other hand it is very stable, doesn't have any side effects and is completely transparent to the business logic. I never use batch values higher then 100. It is sufficient to reduce the N+1 to some reasonable amount of queries.
我发现这篇文章很有帮助。我相信批量获取可以应用于集合和父级,而子选择只能应用于集合。
对于集合的获取策略,子选择将被执行一次(因为批处理大小实际上是无穷大),而使用批量获取时,SQL 语句可能会执行多次。
I found this article to be helpful. I believe batch-fetching can be applied on both the collection and the parent, while subselect can only be applied on a collection.
In case of a fetching strategy for collections, a subselect will be executed once (because the batch-size is effectively infinity), while with batch-fetching the SQL statement might be executed multiple times.