【问题标题】:EclipseLink generates cartesian plan instead of (inner) joins in SQL. Why?EclipseLink 生成笛卡尔计划而不是 SQL 中的(内部)联接。为什么?
【发布时间】:2011-01-28 03:41:06
【问题描述】:

在 Hibernate 是我的持久性提供程序的项目中,我可以使用“join fetch”表达式发出查询,Hibernate 将生成反映以下内容的 SQL:包含使用有效比较路径的连接表达式的 SQL。

然而,EclipseLink 会发出带有丑陋笛卡尔计划的 SQL,这会严重损害性能。在阅读此article 时,它提到急切地获取可能会生成笛卡尔计划,但它很容易忘记其他提供者(Hibernate)可以优化它。

那么,是否可以指示 EclipseLink 优化这些查询?我相信很少有关系可以通过使用 @FetchJoin 注释来优化,但我希望找到不包括在域模型上传播 ORM 特定注释的东西。

例如,这是我作为 JPQL 发出的(动态)查询:

String query = "select w from WorkOrder w " +
            "inner join fetch w.type " +
            "inner join fetch w.details " +
            "inner join fetch w.project " +
            "inner join fetch w.priority " +
            "inner join fetch w.networkElement ";

这里是 EclipseLink 输出:

SELECT t1.ID, t1.CREATION, ... (the fetch fields here)
FROM swa_network_element t5, swa_priorities t4, swa_dispatch_project t3, swa_work_order_detail t2, swa_work_orders t1, swa_work_order_type t0
WHERE ((t1.alpha_id LIKE '%TSK%') AND (((((t0.ID = t1.TYPE_ID) AND (t2.worder_id = t1.ID)) AND (t3.id = t1.project_id)) AND (t4.ID = t1.priority_id)) AND (t5.ID = t1.ne_id))) ORDER BY t1.CREATION DESC

最好的问候, 罗德里戈·哈特曼

【问题讨论】:

  • 尝试在 EclipseLink 论坛上发帖,但也没有得到回复。敏感话题?
  • 发现您的问题涉及到相同的问题。今天破解它,如果我发现任何东西会回复。
  • 我们的 DBA 告诉我,如果 EclipseLink 在 WHERE 子句中加入表,就 $QL $erver 而言,它不会对查询性能产生特别影响。我看过他的测试,我对结果很满意。现在唯一剩下的问题是当 EclipseLink 在没有任何充分理由的情况下添加同一个表 两次 时。对于这些特定的查询,我不得不涉足 Criteria 以获得令人满意的结果。在这种时候,我想念 Hibernate。

标签: orm jpa performance eclipselink


【解决方案1】:

尝试使用:

@org.eclipse.persistence.annotations.JoinFetch(JoinFetchType.INNER)

-- 或--

@org.eclipse.persistence.annotations.JoinFetch(JoinFetchType.OUTER)

对于可为空的列,建议使用外连接。

我在这个博客中找到了更多信息:http://vard-lokkur.blogspot.com/2010/09/jpa-demystified-episode-1-onetomany-and.html

问候,

维克多·托托雷洛·内托

【讨论】:

  • 另请参阅该博客的a follow up当且仅当您绝对确定该关联实体将始终存在时才使用@JoinFetch(JoinFetchType.INNER) - 例如。当数据库方案不允许其他可能性时。
【解决方案2】:

我不确定你的意思? SQL 似乎是正确的,每个表都有一个连接,哪个表缺少连接?

您期望的 SQL 是什么?

如果您的意思是将连接条件放在 FROM 子句而不是 WHERE 子句中,EclipseLink 会根据需要对外部连接执行此操作,但不会对内部连接执行此操作,因为它对我知道的任何数据库都没有影响.如果你真的想要,你可以配置 EclipseLink 2.4 以使用 DatabasePlatform setPrintInnerJoinInWhereClause(false) API 在 FROM 子句中打印内部连接的连接条件,但它应该不会影响数据库的功能。

关于join fetching笛卡尔问题的博客文章是当您join fetch多个1-m关系时,这可能会导致返回大量数据。由于您需要所有数据,因此无法通过连接获取来优化这一点。在 EclipseLink 中你可以使用批量抓取,这比连接抓取效率更高。

看, http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html

【讨论】:

    猜你喜欢
    • 2015-11-18
    • 2018-10-21
    • 2023-01-03
    • 1970-01-01
    • 2016-10-08
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多