Thread: Another weird one with an UPDATE
I am running an update-query to benchmark various databases; the postgres version is,
UPDATE user_account SET last_name = 'abc'
WHERE user_account_id IN (SELECT user_account_id FROM commercial_entity, commercial_service WHERE yw_account_id IS NULL
AND commercial_entity.commercial_entity_id = commercial_service.commercial_entity_id);
WHERE user_account_id IN (SELECT user_account_id FROM commercial_entity, commercial_service WHERE yw_account_id IS NULL
AND commercial_entity.commercial_entity_id = commercial_service.commercial_entity_id);
The inner query (the select), run by itself, takes about a second. Add the outer query (the update-portion), and the query dies. The machine has been vacuum-analzyed. Here is the explain-analyze:
benchtest=# EXPLAIN ANALYZE UPDATE user_account SET last_name = 'abc'
benchtest-# WHERE user_account_id IN (SELECT user_account_id FROM commercial_entity, commercial_service WHERE yw_account_id IS NULL
benchtest(# AND commercial_entity.commercial_entity_id = commercial_service.commercial_entity_id);
benchtest-# WHERE user_account_id IN (SELECT user_account_id FROM commercial_entity, commercial_service WHERE yw_account_id IS NULL
benchtest(# AND commercial_entity.commercial_entity_id = commercial_service.commercial_entity_id);
Seq Scan on user_account (cost=0.00..813608944.88 rows=36242 width=718) (actual time=15696258.98..16311130.29 rows=3075 loops=1) Filter: (subplan)
SubPlan
-> Materialize (cost=11224.77..11224.77 rows=86952 width=36) (actual time=0.06..106.40 rows=84831 loops=72483)
-> Merge Join (cost=0.00..11224.77 rows=86952 width=36) (actual time=0.21..1845.13 rows=85158 loops=1)
Merge Cond: ("outer".commercial_entity_id = "inner".commercial_entity_id)
-> Index Scan using commercial_entity_pkey on commercial_entity (cost=0.00..6787.27 rows=77862 width=24) (actual time=0.06..469.56 rows=78132 loops=1)
Filter: (yw_account_id IS NULL)
-> Index Scan using comm_serv_comm_ent_id_i on commercial_service (cost=0.00..2952.42 rows=88038 width=12) (actual time=0.03..444.80 rows=88038 loops=1)
Total runtime: 16332976.21 msec
(10 rows)
SubPlan
-> Materialize (cost=11224.77..11224.77 rows=86952 width=36) (actual time=0.06..106.40 rows=84831 loops=72483)
-> Merge Join (cost=0.00..11224.77 rows=86952 width=36) (actual time=0.21..1845.13 rows=85158 loops=1)
Merge Cond: ("outer".commercial_entity_id = "inner".commercial_entity_id)
-> Index Scan using commercial_entity_pkey on commercial_entity (cost=0.00..6787.27 rows=77862 width=24) (actual time=0.06..469.56 rows=78132 loops=1)
Filter: (yw_account_id IS NULL)
-> Index Scan using comm_serv_comm_ent_id_i on commercial_service (cost=0.00..2952.42 rows=88038 width=12) (actual time=0.03..444.80 rows=88038 loops=1)
Total runtime: 16332976.21 msec
(10 rows)
Here are the relevant parts of the schema:
USER_ACCOUNT
Column | Type | Modifiers
-------------------------------+-----------------------------+-----------------------------
user_account_id | numeric(10,0) | not null
first_name | character varying(100) |
last_name | character varying(100) |
Indexes: user_account_pkey primary key btree (user_account_id),
usr_acc_last_name_i btree (last_name),
Foreign Key constraints: $1 FOREIGN KEY (lang_id) REFERENCES lang(lang_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$2 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$3 FOREIGN KEY (user_role_id) REFERENCES user_role(user_role_id) ON UPDATE NO ACTION ON DELETE NO ACTION
-------------------------------+-----------------------------+-----------------------------
user_account_id | numeric(10,0) | not null
first_name | character varying(100) |
last_name | character varying(100) |
Indexes: user_account_pkey primary key btree (user_account_id),
usr_acc_last_name_i btree (last_name),
Foreign Key constraints: $1 FOREIGN KEY (lang_id) REFERENCES lang(lang_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$2 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$3 FOREIGN KEY (user_role_id) REFERENCES user_role(user_role_id) ON UPDATE NO ACTION ON DELETE NO ACTION
COMMERCIAL_ENTITY
Column | Type | Modifiers
---------------------------+-----------------------------+-------------------------------------------------------------
commercial_entity_id | numeric(10,0) | not null
yw_account_id | numeric(10,0) |
Indexes: commercial_entity_pkey primary key btree (commercial_entity_id),
comm_ent_yw_acc_id_i btree (yw_account_id)
Foreign Key constraints: $1 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$2 FOREIGN KEY (user_account_id) REFERENCES user_account(user_account_id) ON UPDATE NO ACTION ON DELETE NO ACTION
---------------------------+-----------------------------+-------------------------------------------------------------
commercial_entity_id | numeric(10,0) | not null
yw_account_id | numeric(10,0) |
Indexes: commercial_entity_pkey primary key btree (commercial_entity_id),
comm_ent_yw_acc_id_i btree (yw_account_id)
Foreign Key constraints: $1 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$2 FOREIGN KEY (user_account_id) REFERENCES user_account(user_account_id) ON UPDATE NO ACTION ON DELETE NO ACTION
COMMERCIAL_SERVICE
Column | Type | Modifiers
----------------------+---------------+-----------
commercial_entity_id | numeric(10,0) | not null
service_type_id | numeric(10,0) | not null
source_id | numeric(10,0) | not null
Indexes: commercial_service_pkey primary key btree (commercial_entity_id, service_type_id),
comm_serv_comm_ent_id_i btree (commercial_entity_id),
comm_serv_serv_type_id_i btree (service_type_id),
comm_serv_source_id_i btree (source_id)
Foreign Key constraints: $1 FOREIGN KEY (commercial_entity_id) REFERENCES commercial_entity(commercial_entity_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$2 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$3 FOREIGN KEY (service_type_id) REFERENCES service_type(service_type_id) ON UPDATE NO ACTION ON DELETE NO ACTION
----------------------+---------------+-----------
commercial_entity_id | numeric(10,0) | not null
service_type_id | numeric(10,0) | not null
source_id | numeric(10,0) | not null
Indexes: commercial_service_pkey primary key btree (commercial_entity_id, service_type_id),
comm_serv_comm_ent_id_i btree (commercial_entity_id),
comm_serv_serv_type_id_i btree (service_type_id),
comm_serv_source_id_i btree (source_id)
Foreign Key constraints: $1 FOREIGN KEY (commercial_entity_id) REFERENCES commercial_entity(commercial_entity_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$2 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$3 FOREIGN KEY (service_type_id) REFERENCES service_type(service_type_id) ON UPDATE NO ACTION ON DELETE NO ACTION
Here is the postgres.conf (or the variables that are not commented out):
tcpip_socket = true
max_connections = 500
max_connections = 500
shared_buffers = 32768 # min max_connections*2 or 16, 8KB each
wal_buffers = 128 # min 4, typically 8KB each
wal_buffers = 128 # min 4, typically 8KB each
sort_mem = 4096 # min 64, size in KB
effective_cache_size = 50000 # typically 8KB each
effective_cache_size = 50000 # typically 8KB each
Is it a problem with "IN"?
David
Sorry - just found the FAQ (http://jamesthornton.com/postgres/FAQ/faq-english.html#4.22) on how IN is very slow.
So I rewrote the query:
\o ./data/temp.txt
SELECT current_timestamp;
UPDATE user_account SET last_name = 'abc'
WHERE EXISTS (SELECT ua.user_account_id FROM user_account ua, commercial_entity ce, commercial_service cs
WHERE ua.user_account_id = ce.user_account_id AND ce.commercial_entity_id = cs.commercial_entity_id);
WHERE EXISTS (SELECT ua.user_account_id FROM user_account ua, commercial_entity ce, commercial_service cs
WHERE ua.user_account_id = ce.user_account_id AND ce.commercial_entity_id = cs.commercial_entity_id);
SELECT current_timestamp;
\o
EXISTS is kind of a weird statement, and it doesn't appear to be identical (the number of rows updated was 72,000 rather than 3500). It also took 4 minutes to execute.
Is there any way around this other than breaking the query into two? As in:
pstmt1 = conn.preprareStatement("SELECT ua.user_account_id FROM user_account ua, commercial_entity ce, commercial_service cs
WHERE ua.user_account_id = ce.user_account_id AND ce.commercial_entity_id = cs.commercial_entity_id");
WHERE ua.user_account_id = ce.user_account_id AND ce.commercial_entity_id = cs.commercial_entity_id");
rset = pstmt1.executeQuery();
while (rset.next())
{
pstmt2 = conn.prepareStatement("UPDATE user_account SET last_name = 'abc' WHERE user_account_id = ?");
pstmt2.setLong(1, rset.getLong(1));
...
}
Unfort, that will be alot of data moved from Postgres->middle-tier (Weblogic/Resin), which is inefficient.
Anyone see another solution?
David.
----- Original Message -----From: David GriffithsSent: Saturday, October 11, 2003 12:44 PMSubject: [PERFORM] Another weird one with an UPDATEI am running an update-query to benchmark various databases; the postgres version is,UPDATE user_account SET last_name = 'abc'
WHERE user_account_id IN (SELECT user_account_id FROM commercial_entity, commercial_service WHERE yw_account_id IS NULL
AND commercial_entity.commercial_entity_id = commercial_service.commercial_entity_id);The inner query (the select), run by itself, takes about a second. Add the outer query (the update-portion), and the query dies. The machine has been vacuum-analzyed. Here is the explain-analyze:benchtest=# EXPLAIN ANALYZE UPDATE user_account SET last_name = 'abc'
benchtest-# WHERE user_account_id IN (SELECT user_account_id FROM commercial_entity, commercial_service WHERE yw_account_id IS NULL
benchtest(# AND commercial_entity.commercial_entity_id = commercial_service.commercial_entity_id);Seq Scan on user_account (cost=0.00..813608944.88 rows=36242 width=718) (actual time=15696258.98..16311130.29 rows=3075 loops=1) Filter: (subplan)
SubPlan
-> Materialize (cost=11224.77..11224.77 rows=86952 width=36) (actual time=0.06..106.40 rows=84831 loops=72483)
-> Merge Join (cost=0.00..11224.77 rows=86952 width=36) (actual time=0.21..1845.13 rows=85158 loops=1)
Merge Cond: ("outer".commercial_entity_id = "inner".commercial_entity_id)
-> Index Scan using commercial_entity_pkey on commercial_entity (cost=0.00..6787.27 rows=77862 width=24) (actual time=0.06..469.56 rows=78132 loops=1)
Filter: (yw_account_id IS NULL)
-> Index Scan using comm_serv_comm_ent_id_i on commercial_service (cost=0.00..2952.42 rows=88038 width=12) (actual time=0.03..444.80 rows=88038 loops=1)
Total runtime: 16332976.21 msec
(10 rows)Here are the relevant parts of the schema:USER_ACCOUNTColumn | Type | Modifiers
-------------------------------+-----------------------------+-----------------------------
user_account_id | numeric(10,0) | not null
first_name | character varying(100) |
last_name | character varying(100) |
Indexes: user_account_pkey primary key btree (user_account_id),
usr_acc_last_name_i btree (last_name),
Foreign Key constraints: $1 FOREIGN KEY (lang_id) REFERENCES lang(lang_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$2 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$3 FOREIGN KEY (user_role_id) REFERENCES user_role(user_role_id) ON UPDATE NO ACTION ON DELETE NO ACTION
COMMERCIAL_ENTITYColumn | Type | Modifiers
---------------------------+-----------------------------+-------------------------------------------------------------
commercial_entity_id | numeric(10,0) | not null
yw_account_id | numeric(10,0) |
Indexes: commercial_entity_pkey primary key btree (commercial_entity_id),
comm_ent_yw_acc_id_i btree (yw_account_id)
Foreign Key constraints: $1 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$2 FOREIGN KEY (user_account_id) REFERENCES user_account(user_account_id) ON UPDATE NO ACTION ON DELETE NO ACTIONCOMMERCIAL_SERVICEColumn | Type | Modifiers
----------------------+---------------+-----------
commercial_entity_id | numeric(10,0) | not null
service_type_id | numeric(10,0) | not null
source_id | numeric(10,0) | not null
Indexes: commercial_service_pkey primary key btree (commercial_entity_id, service_type_id),
comm_serv_comm_ent_id_i btree (commercial_entity_id),
comm_serv_serv_type_id_i btree (service_type_id),
comm_serv_source_id_i btree (source_id)
Foreign Key constraints: $1 FOREIGN KEY (commercial_entity_id) REFERENCES commercial_entity(commercial_entity_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$2 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION,
$3 FOREIGN KEY (service_type_id) REFERENCES service_type(service_type_id) ON UPDATE NO ACTION ON DELETE NO ACTIONHere is the postgres.conf (or the variables that are not commented out):tcpip_socket = true
max_connections = 500shared_buffers = 32768 # min max_connections*2 or 16, 8KB each
wal_buffers = 128 # min 4, typically 8KB eachsort_mem = 4096 # min 64, size in KB
effective_cache_size = 50000 # typically 8KB eachIs it a problem with "IN"?David
On Sat, 11 Oct 2003, David Griffiths wrote: > Sorry - just found the FAQ ( > http://jamesthornton.com/postgres/FAQ/faq-english.html#4.22 > <http://jamesthornton.com/postgres/FAQ/faq-english.html#4.22> ) on how > IN is very slow. > > So I rewrote the query: > > \o ./data/temp.txt > SELECT current_timestamp; > UPDATE user_account SET last_name = 'abc' > WHERE EXISTS (SELECT ua.user_account_id FROM user_account ua, > commercial_entity ce, commercial_service cs > WHERE ua.user_account_id = ce.user_account_id AND > ce.commercial_entity_id = cs.commercial_entity_id); > SELECT current_timestamp; I don't think that's the query you want. You're not binding the subselect to the outer values of user_account. I think you want something like: UPDATE user_account SET last_name = 'abc' WHERE EXISTS (SELECT 1 FROM commercial_entity ce, commercial_service cs WHERE user_account.user_account_id = ce.user_account_id AND ce.commercial_entity_id = cs.commercial_entity_id);
Thanks - that worked. David ----- Original Message ----- From: "Stephan Szabo" <sszabo@megazone.bigpanda.com> To: "David Griffiths" <dgriffiths@boats.com> Cc: <pgsql-performance@postgresql.org> Sent: Saturday, October 11, 2003 3:34 PM Subject: Re: [PERFORM] Another weird one with an UPDATE > On Sat, 11 Oct 2003, David Griffiths wrote: > > > Sorry - just found the FAQ ( > > http://jamesthornton.com/postgres/FAQ/faq-english.html#4.22 > > <http://jamesthornton.com/postgres/FAQ/faq-english.html#4.22> ) on how > > IN is very slow. > > > > So I rewrote the query: > > > > \o ./data/temp.txt > > SELECT current_timestamp; > > UPDATE user_account SET last_name = 'abc' > > WHERE EXISTS (SELECT ua.user_account_id FROM user_account ua, > > commercial_entity ce, commercial_service cs > > WHERE ua.user_account_id = ce.user_account_id AND > > ce.commercial_entity_id = cs.commercial_entity_id); > > SELECT current_timestamp; > > I don't think that's the query you want. You're not binding the subselect > to the outer values of user_account. > > I think you want something like: > UPDATE user_account SET last_name = 'abc' > WHERE EXISTS (SELECT 1 FROM commercial_entity ce, commercial_service cs > WHERE user_account.user_account_id = ce.user_account_id AND > ce.commercial_entity_id = cs.commercial_entity_id);
[snip] > I think you want something like: > UPDATE user_account SET last_name = 'abc' > WHERE EXISTS (SELECT 1 FROM commercial_entity ce, commercial_service cs > WHERE user_account.user_account_id = ce.user_account_id AND > ce.commercial_entity_id = cs.commercial_entity_id); Unfort, this is still taking a long time. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- ------- Seq Scan on user_account (cost=0.00..748990.51 rows=36242 width=716) (actual time=10262.50..26568.03 rows=3771 loops=1) Filter: (subplan) SubPlan -> Nested Loop (cost=0.00..11.47 rows=1 width=24) (actual time=0.24..0.24 rows=0 loops=72483) -> Index Scan using comm_ent_usr_acc_id_i on commercial_entity ce (cost=0.00..4.12 rows=1 width=12) (actual time=0.05..0.05 rows=0 loops=72483) Index Cond: ($0 = user_account_id) -> Index Scan using comm_serv_comm_ent_id_i on commercial_service cs (cost=0.00..7.32 rows=3 width=12) (actual time=1.72..1.72 rows=0 loops=7990) Index Cond: ("outer".commercial_entity_id = cs.commercial_entity_id) Total runtime: 239585.09 msec (9 rows) Anyone have any thoughts? David
David Griffiths wrote: >>I think you want something like: >>UPDATE user_account SET last_name = 'abc' >> WHERE EXISTS (SELECT 1 FROM commercial_entity ce, commercial_service cs >> WHERE user_account.user_account_id = ce.user_account_id AND >> ce.commercial_entity_id = cs.commercial_entity_id); > > Unfort, this is still taking a long time. > ------- > Seq Scan on user_account (cost=0.00..748990.51 rows=36242 width=716) Do you have an index on user_account.user_account_id? Joe
On Sun, 12 Oct 2003, David Griffiths wrote: > [snip] > > > I think you want something like: > > UPDATE user_account SET last_name = 'abc' > > WHERE EXISTS (SELECT 1 FROM commercial_entity ce, commercial_service cs > > WHERE user_account.user_account_id = ce.user_account_id AND > > ce.commercial_entity_id = cs.commercial_entity_id); > > Unfort, this is still taking a long time. Hmm, does UPDATE user_account SET last_name='abc' FROM commercial_entity ce, commercial_service cs WHERE user_account.user_account_id = ce.user_account_id AND ce.commercial_entity_id=cs.commercial_entity_id; give the right results... That might end up being faster.
Yes, the query operates only on indexed columns (all numeric(10)'s). Column | Type | Modifiers -------------------------------+-----------------------------+-------------- --------------- user_account_id | numeric(10,0) | not null [snip] Indexes: user_account_pkey primary key btree (user_account_id), Foreign Key constraints: $1 FOREIGN KEY (lang_id) REFERENCES lang(lang_id) ON UPDATE NO ACTION ON DELETE NO ACTION, $2 FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION, $3 FOREIGN KEY (user_role_id) REFERENCES user_role(user_role_id) ON UPDATE NO ACTION ON DELETE NO ACTION David ----- Original Message ----- From: "Joe Conway" <mail@joeconway.com> To: "David Griffiths" <dgriffiths@boats.com> Cc: <pgsql-performance@postgresql.org> Sent: Sunday, October 12, 2003 6:37 PM Subject: Re: [PERFORM] Another weird one with an UPDATE > David Griffiths wrote: > >>I think you want something like: > >>UPDATE user_account SET last_name = 'abc' > >> WHERE EXISTS (SELECT 1 FROM commercial_entity ce, commercial_service cs > >> WHERE user_account.user_account_id = ce.user_account_id AND > >> ce.commercial_entity_id = cs.commercial_entity_id); > > > > Unfort, this is still taking a long time. > > ------- > > Seq Scan on user_account (cost=0.00..748990.51 rows=36242 width=716) > > Do you have an index on user_account.user_account_id? > > Joe
It's a slight improvement, but that could be other things as well. I'd read that how you tune Postgres will determine how the optimizer works on a query (sequential scan vs index scan). I am going to post all I've done with tuning tommorow, and see if I've done anything dumb. I've found some contradictory advice, and I'm still a bit hazy on how/why Postgres trusts the OS to do caching. I'll post it all tommorow. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- ---------------- Merge Join (cost=11819.21..15258.55 rows=12007 width=752) (actual time=4107.64..5587.81 rows=20880 loops=1) Merge Cond: ("outer".commercial_entity_id = "inner".commercial_entity_id) -> Index Scan using comm_serv_comm_ent_id_i on commercial_service cs (cost=0.00..3015.53 rows=88038 width=12) (actual time=0.05..487.23 rows=88038 loops=1) -> Sort (cost=11819.21..11846.08 rows=10752 width=740) (actual time=3509.07..3955.15 rows=25098 loops=1) Sort Key: ce.commercial_entity_id -> Merge Join (cost=0.00..9065.23 rows=10752 width=740) (actual time=0.18..2762.13 rows=7990 loops=1) Merge Cond: ("outer".user_account_id = "inner".user_account_id) -> Index Scan using user_account_pkey on user_account (cost=0.00..8010.39 rows=72483 width=716) (actual time=0.05..2220.86 rows=72483 loops=1) -> Index Scan using comm_ent_usr_acc_id_i on commercial_entity ce (cost=0.00..4787.69 rows=78834 width=24) (actual time=0.02..55.64 rows=7991 loops=1) Total runtime: 226239.77 msec (10 rows) David ----- Original Message ----- From: "Stephan Szabo" <sszabo@megazone.bigpanda.com> To: "David Griffiths" <dgriffiths@boats.com> Cc: <pgsql-performance@postgresql.org> Sent: Sunday, October 12, 2003 6:48 PM Subject: Re: [PERFORM] Another weird one with an UPDATE > On Sun, 12 Oct 2003, David Griffiths wrote: > > > [snip] > > > > > I think you want something like: > > > UPDATE user_account SET last_name = 'abc' > > > WHERE EXISTS (SELECT 1 FROM commercial_entity ce, commercial_service cs > > > WHERE user_account.user_account_id = ce.user_account_id AND > > > ce.commercial_entity_id = cs.commercial_entity_id); > > > > Unfort, this is still taking a long time. > > Hmm, does > UPDATE user_account SET last_name='abc' > FROM commercial_entity ce, commercial_service cs > WHERE user_account.user_account_id = ce.user_account_id AND > ce.commercial_entity_id=cs.commercial_entity_id; > give the right results... That might end up being faster.
David Griffiths wrote: > It's a slight improvement, but that could be other things as well. > > I'd read that how you tune Postgres will determine how the optimizer works > on a query (sequential scan vs index scan). I am going to post all I've done > with tuning tommorow, and see if I've done anything dumb. I've found some > contradictory advice, and I'm still a bit hazy on how/why Postgres trusts > the OS to do caching. I'll post it all tommorow. > > ---------------------------------------------------------------------------- > ---------------------------------------------------------------------------- > ---------------- > Merge Join (cost=11819.21..15258.55 rows=12007 width=752) (actual > time=4107.64..5587.81 rows=20880 loops=1) > Merge Cond: ("outer".commercial_entity_id = "inner".commercial_entity_id) > -> Index Scan using comm_serv_comm_ent_id_i on commercial_service cs > (cost=0.00..3015.53 rows=88038 width=12) (actual time=0.05..487.23 > rows=88038 loops=1) > -> Sort (cost=11819.21..11846.08 rows=10752 width=740) (actual > time=3509.07..3955.15 rows=25098 loops=1) > Sort Key: ce.commercial_entity_id I think this is the problem. Is there an index on ce.commercial_entity_id? > -> Merge Join (cost=0.00..9065.23 rows=10752 width=740) (actual > time=0.18..2762.13 rows=7990 loops=1) > Merge Cond: ("outer".user_account_id = > "inner".user_account_id) > -> Index Scan using user_account_pkey on user_account > (cost=0.00..8010.39 rows=72483 width=716) (actual time=0.05..2220.86 > rows=72483 loops=1) > -> Index Scan using comm_ent_usr_acc_id_i on > commercial_entity ce (cost=0.00..4787.69 rows=78834 width=24) (actual > time=0.02..55.64 rows=7991 loops=1) In this case of comparing account ids, its using two index scans. In the entity field though, it chooses a sort. I think there is an index missing. The costs are also shot up as well. > Total runtime: 226239.77 msec Standard performance question. What was the last time these tables/database were vacuumed. Have you tuned postgresql.conf correctly? HTH Shridhar
David Griffiths wrote: > Yes, the query operates only on indexed columns (all numeric(10)'s). > > Column | Type | > Modifiers > -------------------------------+-----------------------------+-------------- > --------------- > user_account_id | numeric(10,0) | not null > [snip] > Indexes: user_account_pkey primary key btree (user_account_id), > Foreign Key constraints: $1 FOREIGN KEY (lang_id) REFERENCES lang(lang_id) > ON UPDATE NO ACTION ON DELETE NO ACTION, > $2 FOREIGN KEY (source_id) REFERENCES > source(source_id) ON UPDATE NO ACTION ON DELETE NO ACTION, > $3 FOREIGN KEY (user_role_id) REFERENCES > user_role(user_role_id) ON UPDATE NO ACTION ON DELETE NO ACTION And what about commercial_entity.user_account_id. Is it indexed and what is its data type (i.e. does it match numeric(10,0))? Also, have you run VACUUM ANALYZE lately? Joe
> And what about commercial_entity.user_account_id. Is it indexed and what > is its data type (i.e. does it match numeric(10,0))? Yup - all columns in the statement are indexed, and they are all numeric(10,0). > Also, have you run VACUUM ANALYZE lately? Yup - just before the last run. Will get together my tuning data now. David