X-Original-To: pgsql-sql@postgresql.org Received: from localhost (postgresql.org [64.49.215.8]) by postgresql.org (Postfix) with ESMTP id 7825B475925 for ; Mon, 3 Mar 2003 14:17:32 -0500 (EST) Received: from postgresql.org ([64.49.215.8]) by localhost (postgresql.org [64.49.215.8:10024]) (amavisd-new) with SMTP id 82476-01 for ; Mon, 3 Mar 2003 14:17:30 -0500 (EST) Received: from sss.pgh.pa.us (unknown [192.204.191.242]) by postgresql.org (Postfix) with ESMTP id 5EB2E475843 for ; Mon, 3 Mar 2003 14:17:30 -0500 (EST) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss.pgh.pa.us (8.12.6/8.12.6) with ESMTP id h23JHJ5u015485; Mon, 3 Mar 2003 14:17:19 -0500 (EST) To: Josh Berkus Cc: Stephan Szabo , Nicolas Fertig , pgsql-sql@postgresql.org Subject: Re: OUTER JOIN with filter In-reply-to: <200303031030.11785.josh@agliodbs.com> References: <20030301232815.Q24208-100000@megazone23.bigpanda.com> <200303031030.11785.josh@agliodbs.com> Comments: In-reply-to Josh Berkus message dated "Mon, 03 Mar 2003 10:30:11 -0800" Date: Mon, 03 Mar 2003 14:17:19 -0500 Message-ID: <15484.1046719039@sss.pgh.pa.us> From: Tom Lane X-Virus-Scanned: by amavisd-new X-Archive-Number: 200303/88 X-Sequence-Number: 12128 Josh Berkus writes: > For that matter, in a few queries I've found that it pays to force the > planner's hand by repeating some of the clauses in the WHERE clause in the > JOIN as well, as: > SELECT a.x, b.y, c.z > FROM a JOIN b ON (a.id = b.a_id AND b.type = 'm') > LEFT OUTER JOIN c ON (b.id = c.b_id) > WHERE b.type = 'm' > The logic is fine. The issue comes where the outer joined table is several > times larger than the main queried table. The planner should recognize the > possibility of filtering the records in the joined table before joining in > order to minimize the join operation. AFAIR, it's always done that; certainly the above query looks quite redundant to me. Note though that pushing down the WHERE clause is only legal because b is on the outer side of the join. A comparable query in the 7.3 regression database is regression=# explain select * from regression-# tenk1 a join tenk1 b on (a.unique1 = b.unique1) regression-# left join tenk1 c on (b.unique2 = c.unique2) regression-# where b.thousand = 999; QUERY PLAN ------------------------------------------------------------------------------------------- Nested Loop (cost=0.00..572.49 rows=10 width=732) -> Nested Loop (cost=0.00..542.55 rows=10 width=488) -> Seq Scan on tenk1 b (cost=0.00..483.00 rows=10 width=244) Filter: (thousand = 999) -> Index Scan using tenk1_unique1 on tenk1 a (cost=0.00..6.01 rows=1 width=244) Index Cond: (a.unique1 = "outer".unique1) -> Index Scan using tenk1_unique2 on tenk1 c (cost=0.00..3.01 rows=1 width=244) Index Cond: ("outer".unique2 = c.unique2) (8 rows) You can see that the condition on b.thousand does get pushed down to the bottom scan. (There's no index on b.thousand, so we don't get an indexscan --- but we would if there were an index...) regards, tom lane