Hibernate连接语句而不是subselect

时间:2014-05-04 15:56:36

标签: hibernate postgresql

我想让hibernate生成一个连接,而不是一个用于查询集合的子选择,而不是可以使用FetchMode.JOIN配置的连接。

示例表:

root(id, property, <other_properties>)
layer1(id, root_id, <other_properties>)
layer2(id, layer1_id, <other_properties>)
layer3(id, layer2_id, <other_properties>)

以及与layer1-3处于同一级别的集合的其他表。取决于我获得的@Fetch(FetchMode.X)注释

FetchMode.JOIN:

SELECT *
FROM root r 
LEFT OUTER JOIN layer1 L1 ON r.id=L1.root_id 
LEFT OUTER JOIN layer2 L2 ON L1.id=L2.layer1_id 
LEFT OUTER JOIN layer3 L3 ON L2.id=L3.layer2_id 
WHERE r.property=?

这是一个包含大量重复数据的非常宽的结果集。 每个父母另外选择一个其他集合。 E.g。

SELECT ...
FROM other o
WHERE o.root_id = ?

FetchMode.SUBSELECT

稍微好一些,因为每个实体只有一个选择。因此,查询的数量受限定的实体数量而不是查询结果大小。

SELECT L3.*
FROM layer3 L3 
WHERE L3.layer2_id IN (
    SELECT L2.id 
    FROM layer2 L2 
    WHERE L2.layer1_id IN (
        SELECT L1.id 
        FROM layer1 L1 
        WHERE L1.root_id IN (
            SELECT r.id 
            FROM root r 
            WHERE r.property=?
    )))

root和layer1表每个包含~50M条目,layer2和3个表每个~500M。这导致我们的Postgres DB上面的选择(~10分钟)的性能非常糟糕。

我可以让Hibernate生成一个“自下而上”的连接语句吗?

SELECT L3.* FROM layer3 L3
JOIN layer2 L2 ON L3.layer2_id = L2.id 
JOIN layer1 L1 ON L2.layer1_id = L1.id
JOIN root r ON L1.root_id = r.id
where r.property = ?

此查询具有相同的结果,但可以在几毫秒内执行。

感谢。

0 个答案:

没有答案