JOOQ 多个联接对同表性能的影响

问题描述 投票:0回答:1

使用带有隐式联接路径的 jooq 3.19,在同一个表上生成多个联接。

  1. 这是预期的吗?

  2. 同一个表上的多个联接是否会带来性能问题?

示例:

DSL.using( SQLDialect.SQLSERVER2017, new Settings().withRenderImplicitJoinToManyType( RenderImplicitJoinType.LEFT_JOIN ) )
.select( Entity.ENTITY.ID ).from( Entity.ENTITY )
.where( Entity.ENTITY.subEntity()
.entity().subEntity()
.entity().subEntity()
.entity().subEntity()
.entity().NAME.eq( "a" ) )
.getSQL()

它生成以下sql:

"select [ENTITY].[ID] from ([ENTITY] 
left outer join ([SUB_ENTITY] [alias_87004649] 
left outer join ([SUB_ENTITY] [alias_112570288] 
left outer join ([SUB_ENTITY] [alias_55342369] 
left outer join ([SUB_ENTITY] [alias_126614199] 
join [ENTITY] [alias_74449122] 
on [alias_126614199].[ENTITY_ID] = [alias_74449122].[ID]) 
on [alias_126614199].[ENTITY_ID] = [alias_55342369].[ID]) 
on [alias_55342369].[ENTITY_ID] = [alias_112570288].[ID]) 
on [alias_112570288].[ENTITY_ID] = [alias_87004649].[ID]) 
on [alias_87004649].[ENTITY_ID] = [ENTITY].[ID]) 
where [alias_74449122].[NAME] = ?"
jooq
1个回答
0
投票

这是预期的吗?

是的。

虽然起初,看起来来回导航相同的外键路径是没有意义的,并且可以消除连接,但实际上不能。每个对多路径段都可以与前面的段创建笛卡尔积,就像任何普通的显式对多连接可以做到这一点。因此,由于需要这种笛卡尔积的可能性很小,jOOQ 在不改变查询逻辑的情况下无法阻止它,所以如果你告诉 jOOQ 多次重新加入同一个表(即使你不打算这样做) ,那么 jOOQ 必须多次重新加入同一个表才能实现您可能想要的查询逻辑。

请注意,跳回到父级实际上已被消除,因为消除它们不会改变您的情况下的查询语义,因为没有投影父列:

同一个表上的多个联接是否会引入性能问题?

当然!这不仅会产生性能问题,还会得到错误的结果。您似乎只是为了“让它发挥作用”而打开

Settings.renderImplicitJoinToManyType
,而没有考虑其含义。但其含义正是我所说的。您的
WHERE
子句现在会产生笛卡尔积,我怀疑您想要也不期望它。

手册中关于隐式对多路径连接的部分对此很清楚

意外的重复对象并不是这种隐式多对多路径连接导致的主要问题。主要问题是,放置在

SELECT

 子句或 
WHERE
 子句(以及其他子句)中的隐式对多路径将能够生成行,而实际上 
SELECT
 仅转换行(如 
Stream.map()
)和 
WHERE
 仅过滤行(如 
Stream.filter()
)。如果这些子句能够有效地生成行,那么 SQL 非常不惯用且令人困惑。

在您的特定情况下,您可能希望使用

连接路径相关

 将谓词移动到 
EXISTS 子查询中,例如

ctx .select(ENTITY.ID) .from(ENTITY) .where(exists( selectOne() .from(ENTITY.subEntity() ... .entity().NAME.eq("a") ) )) .getSQL()
这不需要启用上述有争议的

Settings.renderImplicitJoinToManyType

。您仍然会遇到奇怪的路径和不必要的连接,但至少,您现在不会得到任何笛卡尔积。

摆脱循环

您最了解自己的 RQL 到 jOOQ 翻译语义。如果您

知道可以删除这些循环,那么最好自己做。我希望上面的答案能够澄清为什么 jOOQ 无法自动为您执行此操作。

© www.soinside.com 2019 - 2024. All rights reserved.