Postgres离开加入3个表有条件

时间:2015-06-26 14:15:06

标签: 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)
    LEFT JOIN (
         SELECT c.id FROM c
         WHERE [condition1] [condition4]
    ) AS C USING (id)
    WHERE [condition1]

正如您所看到的,[condition1]对于子查询和外部查询是常见的。

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

我曾试图做一些测试,但他们远未定论。 Postgres是否会发现条件也适用于子查询并传播它?

condition1的示例:

  • WHERE a.id NOT IN (SELECT id FROM {ft_geom_in})(这很慢,我知道,这只是举例)
  • WHERE a.id > x

1 个答案:

答案 0 :(得分:0)

很难给出明确的一般答案,因为很大程度上取决于实际的数据模型(尤其是索引)和查询(条件)。 但是,在许多情况下,将condition1放在已连接的子查询中是有意义的。 这尤其适用于condition2排除的行数少于condition1的情况。 在这种情况下,condition1上的过滤器可能会显着减少condition2的检查次数。

另一方面,子查询中condition1的存在似乎不太可能大大减慢查询速度。

简单测试不提供一般答案,但可以作为说明。

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:condition1

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: ~620.000 ms

A2:没有condition1

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

查询B:condition2排除了很多行。

B1:condition1

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

B2:没有condition1

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

请注意,查询不需要包含子查询。具有简单左连接和公共where clause条件的查询应该更快一些。例如,这相当于查询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