Skip site navigation (1) Skip section navigation (2)

Speedup hint needed, if available? :)

From: Mario Splivalo <mario(dot)splivalo(at)mobart(dot)hr>
To: pgsql-performance(at)postgresql(dot)org
Subject: Speedup hint needed, if available? :)
Date: 2006-05-30 14:18:01
Message-ID: 1148998681.18422.24.camel@localhost.localdomain (view raw, whole thread or download thread mbox)
Lists: pgsql-performance
Hello again.

I have to track user subscriptions to certain mailinglists, and I also
need to track credits users have on those mailinglists. On one side I
have procedures that add credits, on other side I have procedures that
subtract available credits. Add/subtract is pretty intensive, around
30-50 adds per minute (usualy 10 or 100 credits), and around 200-500
subtracts per minute (usualy by one or two credits).

I have created table user_subscriptions to track user subscriptions to
certain mailing list. I have derived subscription_id as primary key. I
have two other tables, user_subscription_credits_given, and
_credits_taken, wich track credits for subscription added or subtracted
to or from certain subscription. I created those two tables so I could
eliminate a lot of UPDATES on user_subscriptions table (if I were to
have a column 'credits' in that table). user_subscriptions table is
projected to have around 100.000 rows, and _credits_given/_credits_taken
table is projected to have around 10.000.000 rows. 

Now, I have filled the tables with test data, and the query results is
kind of poor. It takes almost 50 seconds to get the data for the
particular subscription. Now, is there a way to speed this up, or I need
different approach?

Here is the DDL/DML:

CREATE TABLE user_subscriptions
  subscription_id int4 NOT NULL DEFAULT
  user_id int4 NOT NULL,
  mailinglist_id int4 NOT NULL,
  valid_from timestamptz NOT NULL,
  valid_to timestamptz,
  CONSTRAINT user_subscriptions_pkey PRIMARY KEY (subscription_id)

CREATE TABLE user_subscription_credits_given
  subscription_id int4 NOT NULL,
  credits int4 NOT NULL,
  CONSTRAINT user_subscription_credits_given_fk__subscription_id FOREIGN
KEY (subscription_id)
      REFERENCES user_subscriptions (subscription_id) MATCH SIMPLE

CREATE INDEX fki_user_subscriptions_fk__mailinglist_id
  ON user_subscriptions
  USING btree

CREATE INDEX fki_user_subscriptions_fk__users_id
  ON user_subscriptions
  USING btree

CREATE INDEX fki_user_subscription_credits_given_fk__subscription_id
  ON user_subscription_credits_given
  USING btree

CREATE INDEX fki_user_subscription_credits_taken_fk__subscription_id
  ON user_subscription_credits_taken
  USING btree

Here is the query which gets information on particular user, shows
subscriptions to mailinglists and available credits on those

SELECT u.subscription_id, u.user_id, u.mailinglist_id, u.valid_from,
u.valid_to, sum(credits.credits_given - credits.credits_taken)::integer
AS credits
FROM user_subscriptions u
	(SELECT user_subscription_credits_given.subscription_id,
user_subscription_credits_given.credits AS credits_given, 0 AS
           FROM user_subscription_credits_given
         SELECT user_subscription_credits_taken.subscription_id, 0 AS
credits_given, user_subscription_credits_taken.credits AS credits_taken
           FROM user_subscription_credits_taken) credits 
	ON u.subscription_id = credits.subscription_id
	u.user_id = 1
GROUP BY u.subscription_id, u.user_id, u.mailinglist_id, u.valid_from,

And here is the 'explain analyze' of the above query:

 HashAggregate  (cost=200079055.24..200079055.28 rows=2 width=36)
(actual time=56527.153..56527.163 rows=2 loops=1)
   ->  Nested Loop Left Join  (cost=200033690.72..200078931.34 rows=8260
width=36) (actual time=0.432..54705.844 rows=275366 loops=1)
         Join Filter: ("outer".subscription_id =
         ->  Index Scan using fki_user_subscriptions_fk__users_id on
user_subscriptions u  (cost=0.00..3.03 rows=2 width=28) (actual
time=0.030..0.055 rows=2 loops=1)
               Index Cond: (user_id = 1)
         ->  Materialize  (cost=200033690.72..200045984.63 rows=825991
width=12) (actual time=0.043..22404.107 rows=826032 loops=2)
               ->  Subquery Scan credits
(cost=100000000.00..200028830.73 rows=825991 width=12) (actual
time=0.050..31500.589 rows=826032 loops=1)
                     ->  Append  (cost=100000000.00..200020570.82
rows=825991 width=8) (actual time=0.041..22571.540 rows=826032 loops=1)
                           ->  Subquery Scan "*SELECT* 1"
(cost=100000000.00..100001946.96 rows=78148 width=8) (actual
time=0.031..1226.640 rows=78148 loops=1)
                                 ->  Seq Scan on
user_subscription_credits_given  (cost=100000000.00..100001165.48
rows=78148 width=8) (actual time=0.022..404.253 rows=78148 loops=1)
                           ->  Subquery Scan "*SELECT* 2"
(cost=100000000.00..100018623.86 rows=747843 width=8) (actual
time=0.032..12641.705 rows=747884 loops=1)
                                 ->  Seq Scan on
user_subscription_credits_taken  (cost=100000000.00..100011145.43
rows=747843 width=8) (actual time=0.023..4386.769 rows=747884 loops=1)
 Total runtime: 56536.774 ms
(13 rows)

Thank you all in advance,

Mario Splivalo

"I can do it quick, I can do it cheap, I can do it well. Pick any two."


pgsql-performance by date

Next:From: mcelroy, timDate: 2006-05-30 14:31:08
Subject: pg_dump issue
Previous:From: Alvis TunkelisDate: 2006-05-30 13:05:53
Subject: Re: Selects query stats?

Privacy Policy | About PostgreSQL
Copyright © 1996-2017 The PostgreSQL Global Development Group