Faced weird behaviour with EXISTS
(also applies for NOT EXISTS
) generating different execution plans for
WHERE EXISTS(...)
EXPLAIN ANALYZE
SELECT * FROM books
WHERE EXISTS (SELECT 1 FROM authors WHERE id = books.author_id AND name LIKE 'asd%');
| QUERY PLAN |
| -------------------------------------------------------------------------------------------------------------- |
| Hash Join (cost=218.01..454.43 rows=56 width=40) (actual time=0.975..0.975 rows=0 loops=1) |
| Hash Cond: (books.author_id = authors.id) |
| -> Seq Scan on books (cost=0.00..206.80 rows=11280 width=40) (actual time=0.010..0.010 rows=1 loops=1) |
| -> Hash (cost=217.35..217.35 rows=53 width=4) (actual time=0.943..0.943 rows=0 loops=1) |
| Buckets: 1024 Batches: 1 Memory Usage: 8kB |
| -> Seq Scan on authors (cost=0.00..217.35 rows=53 width=4) (actual time=0.942..0.943 rows=0 loops=1) |
| Filter: ((name)::text ~~ 'asd%'::text) |
| Rows Removed by Filter: 10000 |
| Planning Time: 0.361 ms |
| Execution Time: 1.022 ms |
vs.
WHERE EXISTS(...) = TRUE
EXPLAIN ANALYZE
SELECT * FROM books
WHERE EXISTS (SELECT id FROM authors WHERE id = books.author_id AND name LIKE 'asd%') = True;
| QUERY PLAN |
| -------------------------------------------------------------------------------------------------------------------- |
| Seq Scan on books (cost=0.00..93887.20 rows=5640 width=40) (actual time=2.054..2.054 rows=0 loops=1) |
| Filter: (alternatives: SubPlan 1 or hashed SubPlan 2) |
| Rows Removed by Filter: 10000 |
| SubPlan 1 |
| -> Index Scan using authors_pkey on authors (cost=0.29..8.30 rows=1 width=0) (never executed) |
| Index Cond: (id = books.author_id) |
| Filter: ((name)::text ~~ 'asd%'::text) |
| SubPlan 2 |
| -> Seq Scan on authors authors_1 (cost=0.00..217.35 rows=53 width=4) (actual time=0.931..0.931 rows=0 loops=1) |
| Filter: ((name)::text ~~ 'asd%'::text) |
| Rows Removed by Filter: 10000 |
| Planning Time: 0.298 ms |
| Execution Time: 2.129 ms |
Of particular interest is Hash Join vs. simple Seq Scan and the 2x time diff.
WHERE EXISTS(...) AND TRUE
? I thought it where an interesting question so I tried it with Db2 11.5.AND TRUE
is successfully removed, but= TRUE
generates a different plan.EXISTS(...) = TRUE
is always just noise and should be reduced toEXISTS(...)
. I don't think the Postgres project should bother too much to try and optimize nonsense input (unless there is a good reason).