Re: [PERFORM] Message queue table - strange performance drop with changing limit size.

2010-01-03 Thread Greg Smith

Jesper Krogh wrote:

So what I see is that top 10 takes  1ms, top 50 takes over 500 times
more, and top 1000 only 1.5 times more than top 50.
What can the reason be for the huge drop between limit 10 and limit 50 be?
  


Normally this means you're hitting much higher performing cached 
behavior with the smaller amount that's degrading significantly once 
you've crossed some threshold.  L1 and L2 CPUs caches vs. regular RAM, 
shared_buffers vs. OS cache changes, and cached in RAM vs. read from 
disk are three transition spots where you can hit a large drop in 
performance just by crossing some boundary, going from just fits to 
doesn't fit and data thrashes around.  Larger data sets do not take a 
linearly larger amount of time to run queries against--they sure can 
degrade order of magnitude faster than that.



Indexes:
job_funcid_key UNIQUE, btree (funcid, uniqkey)
funcid_coalesce_priority btree (funcid, coalesce, priority)
funcid_prority_idx2 btree (funcid, priority)
job_jobid_idx btree (jobid)
  


There may very well be an underlying design issue here though.  Indexes 
are far from free to maintain.  You've got a fair number of them with a 
lot of redundant information, which is adding a significant amount of 
overhead for questionable gains.  If you added those just from the 
theory of those are the fields combinations I search via, you really 
need to benchmarking that design decision--it's rarely that easy to 
figure out what works best.  For example, if on average there are a 
small number of things attached to each funcid, the middle two indexes 
here are questionable--it may be more efficient to the system as a whole 
to just grab them all rather than pay the overhead to maintain all these 
indexes.  This is particularly true if you're deleting or updating 
entries ito remove them from this queue, which is going to add a lot of 
VACUUM-related cleanup here as well.


In your situation, I might try dropping both funcid_coalesce_priority 
and then funcid_prority_idx2 and watching what happens to your 
performance and plans, just to learn more about whether they're really 
needed.  A look at the various pg_stat_* view to help determine what 
physical I/O and index use is actually going on might be useful too.


--
Greg Smith2ndQuadrant   Baltimore, MD
PostgreSQL Training, Services and Support
g...@2ndquadrant.com  www.2ndQuadrant.com


--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


Re: [PERFORM] Message queue table - strange performance drop with changing limit size.

2010-01-02 Thread Dimitri Fontaine
Jesper Krogh jes...@krogh.cc writes:
 I have a message queue table, that contains in the order of 1-10m
 messages. It is implemented using TheSchwartz:
 http://search.cpan.org/~bradfitz/TheSchwartz-1.07/lib/TheSchwartz.pm

One way to approach queueing efficiently with PostgreSQL is to rely on
PGQ. New upcoming 3.0 version (alpha1 has been released) contains the
basics for having cooperative consumers, stable version (2.1.10) only
allows multiple consumers to all do the same work (think replication).

  http://wiki.postgresql.org/wiki/Skytools
  http://wiki.postgresql.org/wiki/PGQ_Tutorial

Regards,
-- 
dim

-- 
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


[PERFORM] Message queue table - strange performance drop with changing limit size.

2010-01-01 Thread Jesper Krogh
Hi.

I have a message queue table, that contains in the order of 1-10m
messages. It is implemented using TheSchwartz:
http://search.cpan.org/~bradfitz/TheSchwartz-1.07/lib/TheSchwartz.pm

So when a worker picks the next job it goes into the job table an
select the top X highest priority messages with the funcid that it can
work on. The table looks like this:
db=# \d workqueue.job
  Table workqueue.job
Column |   Type   |   Modifiers

---+--+---
 jobid | integer  | not null default
nextval('workqueue.job_jobid_seq'::regclass)
 funcid| integer  | not null
 arg   | bytea|
 uniqkey   | text |
 insert_time   | integer  |
 run_after | integer  | not null
 grabbed_until | integer  | not null
 priority  | smallint |
 coalesce  | text |
Indexes:
job_funcid_key UNIQUE, btree (funcid, uniqkey)
funcid_coalesce_priority btree (funcid, coalesce, priority)
funcid_prority_idx2 btree (funcid, priority)
job_jobid_idx btree (jobid)

efam=# explain ANALYZe select jobid from workqueue.job where job.funcid
in (3) order by priority asc limit 1000;
   QUERY
PLAN

 Limit  (cost=0.00..2008.53 rows=1000 width=6) (actual
time=0.077..765.169 rows=1000 loops=1)
   -  Index Scan using funcid_prority_idx2 on job
(cost=0.00..7959150.95 rows=3962674 width=6) (actual time=0.074..763.664
rows=1000 loops=1)
 Index Cond: (funcid = 3)
 Total runtime: 766.104 ms
(4 rows)

efam=# explain ANALYZe select jobid from workqueue.job where job.funcid
in (3) order by priority asc limit 50;
  QUERY
PLAN
--
 Limit  (cost=0.00..100.43 rows=50 width=6) (actual time=0.037..505.765
rows=50 loops=1)
   -  Index Scan using funcid_prority_idx2 on job
(cost=0.00..7959150.95 rows=3962674 width=6) (actual time=0.035..505.690
rows=50 loops=1)
 Index Cond: (funcid = 3)
 Total runtime: 505.959 ms
(4 rows)

efam=# explain ANALYZe select jobid from workqueue.job where job.funcid
in (3) order by priority asc limit 10;
 QUERY
PLAN

 Limit  (cost=0.00..20.09 rows=10 width=6) (actual time=0.056..0.653
rows=10 loops=1)
   -  Index Scan using funcid_prority_idx2 on job
(cost=0.00..7959152.95 rows=3962674 width=6) (actual time=0.054..0.640
rows=10 loops=1)
 Index Cond: (funcid = 3)
 Total runtime: 0.687 ms
(4 rows)

So what I see is that top 10 takes  1ms, top 50 takes over 500 times
more, and top 1000 only 1.5 times more than top 50.

What can the reason be for the huge drop between limit 10 and limit 50 be?

-- 
Jesper

-- 
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


Re: [PERFORM] Message queue table - strange performance drop with changing limit size.

2010-01-01 Thread Greg Williamson
Jesper --

I apologize for top-quoting -- a challenged reader. 

This doesn't directly address your question, but I can't help but notice that 
the estimates for rows is _wildly_ off the actual number in each and every 
query. How often / recently have you run ANALYZE on this table ?

Are the timing results consistent over several runs ? It is possible that 
caching effects are entering into the time results.

Greg Williamson



- Original Message 
From: Jesper Krogh jes...@krogh.cc
To: pgsql-performance@postgresql.org
Sent: Fri, January 1, 2010 3:48:43 AM
Subject: [PERFORM] Message queue table - strange performance drop with changing 
limit size. 

Hi.

I have a message queue table, that contains in the order of 1-10m
messages. It is implemented using TheSchwartz:
http://search.cpan.org/~bradfitz/TheSchwartz-1.07/lib/TheSchwartz.pm

So when a worker picks the next job it goes into the job table an
select the top X highest priority messages with the funcid that it can
work on. The table looks like this:
db=# \d workqueue.job
  Table workqueue.job
Column |   Type   |   Modifiers

---+--+---
jobid | integer  | not null default
nextval('workqueue.job_jobid_seq'::regclass)
funcid| integer  | not null
arg   | bytea|
uniqkey   | text |
insert_time   | integer  |
run_after | integer  | not null
grabbed_until | integer  | not null
priority  | smallint |
coalesce  | text |
Indexes:
job_funcid_key UNIQUE, btree (funcid, uniqkey)
funcid_coalesce_priority btree (funcid, coalesce, priority)
funcid_prority_idx2 btree (funcid, priority)
job_jobid_idx btree (jobid)

efam=# explain ANALYZe select jobid from workqueue.job where job.funcid
in (3) order by priority asc limit 1000;
   QUERY
PLAN

Limit  (cost=0.00..2008.53 rows=1000 width=6) (actual
time=0.077..765.169 rows=1000 loops=1)
   -  Index Scan using funcid_prority_idx2 on job
(cost=0.00..7959150.95 rows=3962674 width=6) (actual time=0.074..763.664
rows=1000 loops=1)
 Index Cond: (funcid = 3)
Total runtime: 766.104 ms
(4 rows)

efam=# explain ANALYZe select jobid from workqueue.job where job.funcid
in (3) order by priority asc limit 50;
  QUERY
PLAN
--
Limit  (cost=0.00..100.43 rows=50 width=6) (actual time=0.037..505.765
rows=50 loops=1)
   -  Index Scan using funcid_prority_idx2 on job
(cost=0.00..7959150.95 rows=3962674 width=6) (actual time=0.035..505.690
rows=50 loops=1)
 Index Cond: (funcid = 3)
Total runtime: 505.959 ms
(4 rows)

efam=# explain ANALYZe select jobid from workqueue.job where job.funcid
in (3) order by priority asc limit 10;
 QUERY
PLAN

Limit  (cost=0.00..20.09 rows=10 width=6) (actual time=0.056..0.653
rows=10 loops=1)
   -  Index Scan using funcid_prority_idx2 on job
(cost=0.00..7959152.95 rows=3962674 width=6) (actual time=0.054..0.640
rows=10 loops=1)
 Index Cond: (funcid = 3)
Total runtime: 0.687 ms
(4 rows)

So what I see is that top 10 takes  1ms, top 50 takes over 500 times
more, and top 1000 only 1.5 times more than top 50.

What can the reason be for the huge drop between limit 10 and limit 50 be?

-- 
Jesper

-- 
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance



  

-- 
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


[PERFORM] Message queue table..

2008-04-18 Thread Jesper Krogh


Hi.

I have this message queue table.. currently with 8m+ records. Picking 
the top priority messages seem to take quite long.. it is just a matter 
of searching the index.. (just as explain analyze tells me it does).


Can anyone digest further optimizations out of this output? (All records 
have funcid=4)


# explain analyze SELECT job.jobid, job.funcid, job.arg, job.uniqkey, 
job.insert_time, job.run_after, job.grabbed_until, job.priority, 
job.coalesce FROM workqueue.job  WHERE (job.funcid = 4) AND 
(job.run_after = 1208442668) AND (job.grabbed_until = 1208442668) AND 
(job.coalesce = 'Efam') ORDER BY funcid, priority ASC LIMIT 1

;

   QUERY PLAN 


--
 Limit  (cost=0.00..0.09 rows=1 width=106) (actual 
time=245.273..245.274 rows=1 loops=1)
   -  Index Scan using workqueue_job_funcid_priority_idx on job 
(cost=0.00..695291.80 rows=8049405 width=106) (actual 
time=245.268..245.268 rows=1 loops=1)

 Index Cond: (funcid = 4)
 Filter: ((run_after = 1208442668) AND (grabbed_until = 
1208442668) AND (coalesce = 'Efam'::text))

 Total runtime: 245.330 ms
(5 rows)

--
Jesper

--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


Re: [PERFORM] Message queue table..

2008-04-18 Thread Craig Ringer

Jesper Krogh wrote:


Hi.

I have this message queue table.. currently with 8m+ records. Picking 
the top priority messages seem to take quite long.. it is just a matter 
of searching the index.. (just as explain analyze tells me it does).


Can anyone digest further optimizations out of this output? (All records 
have funcid=4)


You mean all records of interest, right, not all records in the table?

What indexes do you have in place? What's the schema? Can you post a \d 
tablename from psql?


# explain analyze SELECT job.jobid, job.funcid, job.arg, job.uniqkey, 
job.insert_time, job.run_after, job.grabbed_until, job.priority, 
job.coalesce FROM workqueue.job  WHERE (job.funcid = 4) AND 
(job.run_after = 1208442668) AND (job.grabbed_until = 1208442668) AND 
(job.coalesce = 'Efam') ORDER BY funcid, priority ASC LIMIT 1

;

   QUERY PLAN
-- 

 Limit  (cost=0.00..0.09 rows=1 width=106) (actual time=245.273..245.274 
rows=1 loops=1)
   -  Index Scan using workqueue_job_funcid_priority_idx on job 
(cost=0.00..695291.80 rows=8049405 width=106) (actual 
time=245.268..245.268 rows=1 loops=1)

 Index Cond: (funcid = 4)
 Filter: ((run_after = 1208442668) AND (grabbed_until = 
1208442668) AND (coalesce = 'Efam'::text))

 Total runtime: 245.330 ms
(5 rows)


Without seeing the schema and index definitions ... maybe you'd benefit 
from a multiple column index. I'd experiment with an index on 
(funcid,priority) first.


--
Craig Ringer

--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


Re: [PERFORM] Message queue table..

2008-04-18 Thread Jesper Krogh

Craig Ringer wrote:

Jesper Krogh wrote:


Hi.

I have this message queue table.. currently with 8m+ records. 
Picking the top priority messages seem to take quite long.. it is just 
a matter of searching the index.. (just as explain analyze tells me it 
does).


Can anyone digest further optimizations out of this output? (All 
records have funcid=4)


You mean all records of interest, right, not all records in the table?


Actually all the records.. since all the other virtual queues currently 
are empty.


What indexes do you have in place? What's the schema? Can you post a \d 
tablename from psql?


# explain analyze SELECT job.jobid, job.funcid, job.arg, job.uniqkey, 
job.insert_time, job.run_after, job.grabbed_until, job.priority, 
job.coalesce FROM workqueue.job  WHERE (job.funcid = 4) AND 
(job.run_after = 1208442668) AND (job.grabbed_until = 1208442668) 
AND (job.coalesce = 'Efam') ORDER BY funcid, priority ASC LIMIT 1


I found that removing the funcid from the order by made it use a better 
index. (priority, run_after, grabbed_until)  that probably makes sense 
since the funcid doesnt give any value in the index at all.


thanks for leading me back on track.

Jesper

--
Jesper

--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


Re: [PERFORM] Message queue table..

2008-04-18 Thread Tom Lane
Jesper Krogh [EMAIL PROTECTED] writes:
 I have this message queue table.. currently with 8m+ records. Picking 
 the top priority messages seem to take quite long.. it is just a matter 
 of searching the index.. (just as explain analyze tells me it does).

   Limit  (cost=0.00..0.09 rows=1 width=106) (actual 
 time=245.273..245.274 rows=1 loops=1)
 -  Index Scan using workqueue_job_funcid_priority_idx on job 
 (cost=0.00..695291.80 rows=8049405 width=106) (actual 
 time=245.268..245.268 rows=1 loops=1)
   Index Cond: (funcid = 4)
   Filter: ((run_after = 1208442668) AND (grabbed_until = 
 1208442668) AND (coalesce = 'Efam'::text))
   Total runtime: 245.330 ms

Well, what that's doing in English is: scan all the rows with funcid =
4, in priority order, until we hit the first one satisfying the filter
conditions.  Apparently there are a lot of low-priority rows that have
funcid = 4 but not the other conditions.

If it's the coalesce condition that's the problem, an index on
(funcid, coalesce, priority) --- or (coalesce, funcid, priority) ---
would probably help.  I'm not sure there's a simple fix if it's
the other conditions that are really selective.

regards, tom lane

-- 
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


Re: [PERFORM] Message queue table..

2008-04-18 Thread Chris Browne
[EMAIL PROTECTED] (Jesper Krogh) writes:
 I have this message queue table.. currently with 8m+
 records. Picking the top priority messages seem to take quite
 long.. it is just a matter of searching the index.. (just as explain
 analyze tells me it does).

 Can anyone digest further optimizations out of this output? (All
 records have funcid=4)

 # explain analyze SELECT job.jobid, job.funcid, job.arg, job.uniqkey,
 job.insert_time, job.run_after, job.grabbed_until, job.priority,
 job.coalesce FROM workqueue.job  WHERE (job.funcid = 4) AND
 (job.run_after = 1208442668) AND (job.grabbed_until = 1208442668)
 AND (job.coalesce = 'Efam') ORDER BY funcid, priority ASC LIMIT 1
 ;

There might be value in having one or more extra indices...

Here are *plausible* candidates:

1.  If funcid = 4 is highly significant (e.g. - you are always
running this query, and funcid often  4), then you might add a
functional index such as:

  create index job_funcid_run_after on workqueue.job (run_after) where funcid = 
4;
  create index job_funcid_grabbeduntil on workqueue.job (grabbed_until) where 
funcid = 4;

2.  Straight indices like the following:

   create index job_run_after on workqueue.job(run_after);
   create index job_grabbed_until on workqueue.job(grabbed_until);
   create index job_funcid on workqueue.job(funcid);
   create index job_coalesce on workqueue.job(coalesce);

Note that it is _possible_ (though by no means guaranteed) that all
three might prove useful, if you're running 8.1+ where PostgreSQL
supports bitmap index scans.

Another possibility...

3.  You might change your process to process multiple records in a
run so that you might instead run the query (perhaps via a cursor?)

with LIMIT [Something Bigger than 1].

It does seem mighty expensive to run a 245ms query to find just one
record.  It seems quite likely that you could return the top 100 rows
(LIMIT 100) without necessarily finding it runs in any more time.

Returning 100 tuples in 245ms seems rather more acceptable, no?  :-)
-- 
(format nil [EMAIL PROTECTED] cbbrowne linuxfinances.info)
http://linuxdatabases.info/info/linuxdistributions.html
Rules of the Evil Overlord #32. I will not fly into a rage and kill a
messenger who brings me bad news  just to illustrate how evil I really
am. Good messengers are hard to come by.
http://www.eviloverlord.com/

-- 
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance