Thread: ...WHERE TRUE" condition in union results in bad query pla
Hi, (Sorry about double post, I just registered on the performance mailing list, but sent the mail from the wrong account - if anyone responds, please respond to this address) Another issue I have encountered :) Query optimizer glitch: "...WHERE TRUE" condition in union results in bad query plan when sorting the union on a column where for each union-member there exists an index. Find minimal example below. Cheers, Claus PostgreSQL 9.1.3 on x86_64-pc-linux-gnu, compiled by gcc-4.6.real (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1, 64-bit DROP TABLE a; DROP TABLE b; CREATE TABLE a AS SELECT generate_series id FROM generate_series(1, 1000000); CREATE TABLE b AS SELECT generate_series id FROM generate_series(1, 1000000); CREATE INDEX idx_a ON a(id); CREATE INDEX idx_b ON b(id); Q1: Returns immediately: SELECT c.id FROM (SELECT a.id FROM a UNION ALL SELECT b.id FROM b) c ORDER BY c.id LIMIT 10; Q2: Takes a while: SELECT c.id FROM (SELECT a.id FROM a UNION ALL SELECT b.id FROM b WHERE TRUE) c ORDER BY c.id LIMIT 10; Good plan of Q1: EXPLAIN SELECT c.id FROM (SELECT a.id FROM a UNION ALL SELECT b.id FROM b) c ORDER BY c.id LIMIT 10; Limit (cost=0.01..0.57 rows=10 width=4) -> Result (cost=0.01..1123362.70 rows=20000000 width=4) -> Merge Append (cost=0.01..1123362.70 rows=20000000 width=4) Sort Key: a.id -> Index Scan using idx_a on a (cost=0.00..436681.35 rows=10000000 width=4) -> Index Scan using idx_b on b (cost=0.00..436681.35 rows=10000000 width=4) Bad plan of Q2: Does sorting although index scan would be sufficient EXPLAIN SELECT c.id FROM (SELECT a.id FROM a UNION ALL SELECT b.id FROM b WHERE TRUE) c ORDER BY c.id LIMIT 10; Limit (cost=460344.41..460344.77 rows=10 width=4) -> Result (cost=460344.41..1172025.76 rows=20000000 width=4) -> Merge Append (cost=460344.41..1172025.76 rows=20000000 width=4) Sort Key: a.id -> Index Scan using idx_a on a (cost=0.00..436681.35 rows=10000000 width=4) -> Sort (cost=460344.40..485344.40 rows=10000000 width=4) Sort Key: b.id -> Seq Scan on b (cost=0.00..144248.00 rows=10000000 width=4)
Claus Stadler <cstadler@informatik.uni-leipzig.de> writes: > Query optimizer glitch: "...WHERE TRUE" condition in union results in > bad query plan ... Yeah, this is because a nonempty WHERE clause defeats simplifying the UNION ALL into a simple "append relation" (cf is_safe_append_member()). The planner will eventually figure out that WHERE TRUE is a no-op, but that doesn't happen till later (and there are good reasons to do things in that order). Sooner or later I'd like to relax the restriction that appendrel members can't have extra WHERE clauses, but don't hold your breath waiting... regards, tom lane
On Sat, Mar 3, 2012 at 10:03 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Claus Stadler <cstadler@informatik.uni-leipzig.de> writes: >> Query optimizer glitch: "...WHERE TRUE" condition in union results in >> bad query plan ... > > Yeah, this is because a nonempty WHERE clause defeats simplifying the > UNION ALL into a simple "append relation" (cf is_safe_append_member()). > The planner will eventually figure out that WHERE TRUE is a no-op, > but that doesn't happen till later (and there are good reasons to do > things in that order). > > Sooner or later I'd like to relax the restriction that appendrel members > can't have extra WHERE clauses, but don't hold your breath waiting... Does this comment need updating? * Note: the data structure assumes that append-rel members are single * baserels. This is OK for inheritance, but it prevents us from pulling * up a UNION ALL member subquery if it contains a join. While that could * be fixed with a more complex data structure, at present there's not much * point because no improvement in the plan could result. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company
Robert Haas <robertmhaas@gmail.com> writes: > On Sat, Mar 3, 2012 at 10:03 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: >> Sooner or later I'd like to relax the restriction that appendrel members >> can't have extra WHERE clauses, but don't hold your breath waiting... > Does this comment need updating? > * Note: the data structure assumes that append-rel members are single > * baserels. This is OK for inheritance, but it prevents us from pulling > * up a UNION ALL member subquery if it contains a join. While that could > * be fixed with a more complex data structure, at present there's not much > * point because no improvement in the plan could result. No, that's a different restriction. regards, tom lane