Hibernate Subselect与批量提取

时间:2011-08-30 05:42:36

标签: hibernate subquery select-n-plus-1

Hibernate提供(至少)两个选项来解决N + 1查询问题。一个是将FetchMode设置为Subselect,它在该IN子句中生成带有IN子句和子选择的选择。另一种是指定BatchSize,它生成一个带有包含父项ID的IN子句的选择。

两者都有效,但我发现Subselect选项经常遇到性能问题,因为查询父项很复杂。另一方面,使用较大的BatchSize(比如1000),查询的数量和这些查询的复杂性非常小。

我的问题是:你何时会在BatchSize上使用Hibernate的Subselect FetchMode?如果您有非常多的父条目(数千),则子选择可能有意义,但是在其他任何情况下您更喜欢Subselect到BatchSize吗?

编辑:我注意到在处理急切加载时两者之间存在差异。如果您将xToMany关联设置为热切地并通过子选择加载,则会生成一个子选择,就像它是懒惰一样。但是,如果指定BatchSize,则生成的查询将使用外部联接而不是单独的查询。有没有办法强制Hibernate在急切加载时使用单独的批量查询?

2 个答案:

答案 0 :(得分:13)

我不使用subselect,因为它很难控制。在一个具有复杂业务逻辑和大型团队工作的非常大的系统中,很难说哪些查询被使用。子选择可能适用于您确切知道执行了哪个查询的特定情况。

批量提取有一些很大的优势。它并不总是最快,但通常足够快。另一方面,它非常稳定,没有任何副作用,并且对业务逻辑完全透明。我从不使用高于100的批处理值。将N + 1减少到一些合理数量的查询就足够了。

答案 1 :(得分:2)

我发现this article有帮助。我相信批量提取可以应用于集合和父级,而子选择只能应用于集合。

如果是集合的提取策略,子选择将执行一次(因为批量大小实际上是无穷大),而批量提取时,SQL语句可能会多次执行。