Postgresql Postgres使用条件左连接3个表

Postgresql Postgres使用条件左连接3个表,postgresql,join,Postgresql,Join,我有这样一个问题: SELECT x.id FROM x LEFT JOIN ( SELECT a.id FROM a WHERE [condition1] [condition2] ) AS A USING (id) LEFT JOIN ( SELECT b.id FROM b WHERE [condition1] [condition3] ) AS B USING (id) LE

我有这样一个问题:

SELECT x.id 
FROM x
    LEFT JOIN (
         SELECT a.id FROM a
         WHERE [condition1] [condition2]
    ) AS A USING (id)
    LEFT JOIN (
         SELECT b.id FROM b
         WHERE [condition1] [condition3]
    ) AS B USING (id)
    LEFT JOIN (
         SELECT c.id FROM c
         WHERE [condition1] [condition4]
    ) AS C USING (id)
    WHERE [condition1]
正如您所看到的,[condition1]对于子查询和外部查询是通用的

当[通常]出于性能原因,从子查询中删除[condition1]是否值得,因为结果是相同的?请不要给出像“运行它并查看”这样的答案。有很多数据及其变化,因此我们需要良好的最坏情况行为

我试着做了一些测试,但还远远不能得出结论。Postgres是否会发现条件也适用于子查询并传播它

条件1的示例:

其中a.id不在SELECT id FROM{ft_geom_IN}中,这很慢,我知道,这只是个例子 其中a.id>x
很难给出一个明确的通用答案,因为这在很大程度上取决于实际的数据模型,尤其是索引和查询条件。 然而,在许多情况下,在连接的子查询中放置条件1是有意义的。 这尤其适用于条件2排除的行比条件1少得多的情况。 在这种情况下,条件1上的过滤器可能会显著减少条件2的检查次数

另一方面,子查询中条件1的存在似乎不太可能大大降低查询速度

简单的测试不能给出一般的答案,但可以作为一个例子

create table x (id integer, something text);
create table a (id integer, something text);

insert into x select i, i::text from generate_series (1, 1000000) i;
insert into a select i, i::text from generate_series (1, 1000000) i;
查询A:condition2排除了几行

A1:有条件1

查询B:condition2排除了许多行

B1:有条件1

请注意,查询不需要有子查询。在公共where子句中使用简单的左连接和条件的查询应该快一点。例如,这相当于查询B1:

explain analyse
select x.id 
    from x
    left join a using(id)
    where x.id < 500000
    and a.id < 500000 
    and length(a.something) = 1

Average execution time: ~210.000 ms

在较小的模式上解释一些查询应该是有用的。这在很大程度上取决于您希望进入外部查询的条件,以及什么索引能够提供帮助。一般来说,如果没有任何相关的索引,我认为只在左连接子查询中运行该条件会更好,但是如果有appliccable索引,则可能不太有用。谢谢您的详细回复。正如您所说的,这实际上取决于数据的分布,如果不详细介绍QueryPlanner的工作原理,您的答案可能无法得到改进
explain analyse
select x.id 
from x
    left join (
         select id from a
         where length(something) > 1
    ) as a using (id)
where id < 500000;

Average execution time: ~810.000 ms
explain analyse
select x.id 
from x
    left join (
         select id from a
         where id < 500000 and length(something) = 1
    ) as a using (id)
where id < 500000;

Average execution time: ~220.000 ms
explain analyse
select x.id 
from x
    left join (
         select id from a
         where length(something) = 1
    ) as a using (id)
where id < 500000;

Average execution time: ~230.000 ms
explain analyse
select x.id 
    from x
    left join a using(id)
    where x.id < 500000
    and a.id < 500000 
    and length(a.something) = 1

Average execution time: ~210.000 ms