From: | Pierre Ducroquet <p(dot)psql(at)pinaraf(dot)info> |
---|---|
To: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Poor plan when using EXISTS in the expression list |
Date: | 2018-10-04 12:11:51 |
Message-ID: | 2269606.VgtPoMEsXU@pierred-pdoc |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Hello
Our developpers ORM (Django's) sadly can not use EXISTS in the where clauses
without having it in the expression part of the SELECT statement.
I was expecting it to create queries performing a bit worse than queries
without this useless expression, but it turns out this trigger an extremely
poor planning, with an additional Seq Scan of the table referenced in EXISTS.
Thus the query select a.*, exists (select * from b where a_id = a.id) from a
where exists (select * from b where a_id = a.id); can be orders of magnitude
slower than select a.* from a where exists (select * from b where a_id =
a.id);
This has been reproduced on PostgreSQL 9.6 and 11 beta4.
Example :
test=> create table a (id serial primary key, b text);
CREATE TABLE
test=> create table b (id serial primary key, a_id integer not null references
a(id), c text);
CREATE TABLE
test=> explain select a.* from a where exists (select * from b where a_id =
a.id);
QUERY PLAN
-----------------------------------------------------------------------
Hash Join (cost=29.50..62.60 rows=635 width=36)
Hash Cond: (a.id = b.a_id)
-> Seq Scan on a (cost=0.00..22.70 rows=1270 width=36)
-> Hash (cost=27.00..27.00 rows=200 width=4)
-> HashAggregate (cost=25.00..27.00 rows=200 width=4)
Group Key: b.a_id
-> Seq Scan on b (cost=0.00..22.00 rows=1200 width=4)
(7 rows)
test=> explain select a.*, exists (select * from b where a_id = a.id) from a;
QUERY PLAN
-----------------------------------------------------------------
Seq Scan on a (cost=0.00..5314.37 rows=1270 width=37)
SubPlan 1
-> Seq Scan on b (cost=0.00..25.00 rows=6 width=0)
Filter: (a_id = a.id)
SubPlan 2
-> Seq Scan on b b_1 (cost=0.00..22.00 rows=1200 width=4)
(6 rows)
test=> explain select a.*, exists (select * from b where a_id = a.id) from a
where exists (select * from b where a_id = a.id);
QUERY PLAN
-----------------------------------------------------------------------
Hash Join (cost=29.50..2708.43 rows=635 width=37)
Hash Cond: (a.id = b.a_id)
-> Seq Scan on a (cost=0.00..22.70 rows=1270 width=36)
-> Hash (cost=27.00..27.00 rows=200 width=4)
-> HashAggregate (cost=25.00..27.00 rows=200 width=4)
Group Key: b.a_id
-> Seq Scan on b (cost=0.00..22.00 rows=1200 width=4)
SubPlan 1
-> Seq Scan on b b_1 (cost=0.00..25.00 rows=6 width=0)
Filter: (a_id = a.id)
SubPlan 2
-> Seq Scan on b b_2 (cost=0.00..22.00 rows=1200 width=4)
(12 rows)
Thanks
Pierre
From | Date | Subject | |
---|---|---|---|
Next Message | Laurenz Albe | 2018-10-04 12:23:34 | Re: pg_ls_tmpdir() |
Previous Message | Chris Travers | 2018-10-04 12:11:12 | Possible important data point on stats collection, wondering about possible improvement |