Re: [PERFORM] Merge Join vs Nested Loop

2006-09-27 Thread Tobias Brox
[Tom Lane - Tue at 06:09:56PM -0400]
> If your tables are small enough to fit (mostly) in memory, then the
> planner tends to overestimate the cost of a nestloop because it fails to
> account for cacheing effects across multiple scans of the inner table.
> This is addressed in 8.2, but in earlier versions about all you can do
> is reduce random_page_cost, and a sane setting of that (ie not less than
> 1.0) may not be enough to push the cost estimates where you want them.
> Still, reducing random_page_cost ought to be your first recourse.

Thank you.  Reducing the random page hit cost did reduce the nested loop
cost significantly, sadly the merge join costs where reduced even
further, causing the planner to favor those even more than before.
Setting the effective_cache_size really low solved the issue, but I
believe we rather want to have a high effective_cache_size.

Eventually, setting the effective_cache_size to near-0, and setting
random_page_cost to 1 could maybe be a desperate measure.  Another one
is to turn off merge/hash joins and seq scans.  It could be a worthwhile
experiment if nothing else :-)

The bulk of our database is historical data that most often is not
touched at all, though one never knows for sure until the queries have
run all through - so table partitioning is not an option, it seems like.
My general idea is that nested loops would cause the most recent data
and most important part of the indexes to stay in the OS cache.  Does
this make sense from an experts point of view? :-)


---(end of broadcast)---
TIP 4: Have you searched our list archives?

   http://archives.postgresql.org


Re: [PERFORM] Forcing the use of particular execution plans

2006-09-27 Thread Jochem van Dieten

Tim Truman wrote:

Query:
SELECT count(*) as count FROM 
( 
	SELECT *

FROM transaction t, merchant m
		WHERE t.merchant_id = m.id 
			AND m.id = 198

AND t.transaction_date >= '20050101'
AND t.transaction_date <= '20060925'
AND credit_card_no LIKE '%111'

UNION ALL
SELECT *
FROM transaction t, merchant m
WHERE t.merchant_id = m.id
AND m.parent_merchant_id = 198
AND t.transaction_date >= '20050101'
AND t.transaction_date <= '20060925'
AND credit_card_no LIKE '%111'
) AS foobar



Actually, I think the best course of action is to rewrite the query to a 
faster alternative. What you can try is:

SELECT SUM(count) AS count FROM
(
SELECT count(*) AS count
FROM transaction t, merchant m
WHERE t.merchant_id = m.id
AND m.id = 198
AND t.transaction_date >= '20050101'
AND t.transaction_date <= '20060925'
AND credit_card_no LIKE '%111'

UNION ALL
SELECT count(*) AS count
FROM transaction t, merchant m
WHERE t.merchant_id = m.id
AND m.parent_merchant_id = 198
AND t.transaction_date >= '20050101'
AND t.transaction_date <= '20060925'
AND credit_card_no LIKE '%111'
) AS foobar;


The next optimization is to merge the 2 subqueries into one. If you 
schema is such that m.id can not be the same as m.parent_merchant_id I 
think your query can be reduced to:

SELECT count(*) AS count
FROM transaction t, merchant m
WHERE t.merchant_id = m.id
AND
(
m.id = 198
OR
m.parent_merchant_id = 198
)
AND t.transaction_date >= '20050101'
AND t.transaction_date <= '20060925'
AND credit_card_no LIKE '%111'


If m.id can be the same as m.parent_merchant_id you need something like:
SELECT SUM(
CASE WHEN m.id = m.parent_merchant_id THEN 2 ELSE 1 END
) AS count
FROM transaction t, merchant m
WHERE t.merchant_id = m.id
AND
(
m.id = 198
OR
m.parent_merchant_id = 198
)
AND t.transaction_date >= '20050101'
AND t.transaction_date <= '20060925'
AND credit_card_no LIKE '%111'

Jochem

---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
  choose an index scan if your joining column's datatypes do not
  match


Re: [PERFORM] Merge Join vs Nested Loop

2006-09-27 Thread Scott Marlowe
On Wed, 2006-09-27 at 11:48 +0200, Tobias Brox wrote:
> [Tom Lane - Tue at 06:09:56PM -0400]
> > If your tables are small enough to fit (mostly) in memory, then the
> > planner tends to overestimate the cost of a nestloop because it fails to
> > account for cacheing effects across multiple scans of the inner table.
> > This is addressed in 8.2, but in earlier versions about all you can do
> > is reduce random_page_cost, and a sane setting of that (ie not less than
> > 1.0) may not be enough to push the cost estimates where you want them.
> > Still, reducing random_page_cost ought to be your first recourse.
> 
> Thank you.  Reducing the random page hit cost did reduce the nested loop
> cost significantly, sadly the merge join costs where reduced even
> further, causing the planner to favor those even more than before.
> Setting the effective_cache_size really low solved the issue, but I
> believe we rather want to have a high effective_cache_size.
> 
> Eventually, setting the effective_cache_size to near-0, and setting
> random_page_cost to 1 could maybe be a desperate measure.  Another one
> is to turn off merge/hash joins and seq scans.  It could be a worthwhile
> experiment if nothing else :-)
> 
> The bulk of our database is historical data that most often is not
> touched at all, though one never knows for sure until the queries have
> run all through - so table partitioning is not an option, it seems like.
> My general idea is that nested loops would cause the most recent data
> and most important part of the indexes to stay in the OS cache.  Does
> this make sense from an experts point of view? :-)

Have you tried chaning the cpu_* cost options to see how they affect
merge versus nested loop?

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [PERFORM] Merge Join vs Nested Loop

2006-09-27 Thread Tobias Brox
[Scott Marlowe - Wed at 09:58:30AM -0500]
> Have you tried chaning the cpu_* cost options to see how they affect
> merge versus nested loop?

As said in the original post, increasing any of them shifts the planner
towards nested loops instead of merge_join.  I didn't check which one of
the cost constants made the most impact.

---(end of broadcast)---
TIP 5: don't forget to increase your free space map settings


Re: [PERFORM] Merge Join vs Nested Loop

2006-09-27 Thread Scott Marlowe
On Wed, 2006-09-27 at 17:05 +0200, Tobias Brox wrote:
> [Scott Marlowe - Wed at 09:58:30AM -0500]
> > Have you tried chaning the cpu_* cost options to see how they affect
> > merge versus nested loop?
> 
> As said in the original post, increasing any of them shifts the planner
> towards nested loops instead of merge_join.  I didn't check which one of
> the cost constants made the most impact.

So, by decreasing them, you should move away from nested loops then,
right?  Has that not worked for some reason?

---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match


Re: [PERFORM] Merge Join vs Nested Loop

2006-09-27 Thread Tobias Brox
[Scott Marlowe - Wed at 10:19:24AM -0500]
> So, by decreasing them, you should move away from nested loops then,
> right?  Has that not worked for some reason?

I want to move to nested loops, they are empirically faster in many of
our queries, and that makes sense since we've got quite big tables and
most of the queries only touch a small partition of the data.

I've identified that moving any of the cost constants (including
random_page_cost) upwards gives me the right result, but I'm still wary
if this is the right thing to do.  Even if so, what constants should I
target first?  I could of course try to analyze a bit what constants
give the biggest impact.  Then again, we have many more queries hitting
the database than the few I'm doing research into (and those I'm doing
research into is even very simplified versions of the real queries).

---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match


Re: [PERFORM] Merge Join vs Nested Loop

2006-09-27 Thread Scott Marlowe
On Wed, 2006-09-27 at 10:26, Tobias Brox wrote:
> [Scott Marlowe - Wed at 10:19:24AM -0500]
> > So, by decreasing them, you should move away from nested loops then,
> > right?  Has that not worked for some reason?
> 
> I want to move to nested loops, they are empirically faster in many of
> our queries, and that makes sense since we've got quite big tables and
> most of the queries only touch a small partition of the data.
> 
> I've identified that moving any of the cost constants (including
> random_page_cost) upwards gives me the right result, but I'm still wary
> if this is the right thing to do.  Even if so, what constants should I
> target first?  I could of course try to analyze a bit what constants
> give the biggest impact.  Then again, we have many more queries hitting
> the database than the few I'm doing research into (and those I'm doing
> research into is even very simplified versions of the real queries).

Ahh, the other direction then.  I would think it's safer to nudge these
a bit than to drop random page cost to 1 or set effective_cache_size to
1000 etc...

But I'm sure you should test the other queries and / or keep an eye on
your database while running to make sure those changes don't impact
other users.

---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [PERFORM] Merge Join vs Nested Loop

2006-09-27 Thread Tobias Brox
[Scott Marlowe - Wed at 10:31:35AM -0500]
> And remember, you can always change any of those settings in session for
> just this one query to force the planner to make the right decision.

sure ... I could identify the most problematic queries, and hack up the
software application to modify the config settings for those exact
queries ... but it's a very ugly solution. :-)  Particularly if Tom Lane
is correct saying the preferance of merge join instead of nested loop is
indeed a bug.

---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [PERFORM] Forcing the use of particular execution plans

2006-09-27 Thread Dave Dutcher
> -Original Message-
> From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of  Tim Truman
> 
> Hi,
> 
> I have the following query which has been running very slowly 
> and after a
> lot of testing/trial and error I found an execution plan that 
> ran the query
> in a fraction of the time (and then lost the statistics that 
> produced it).
> What I wish to know is how to force the query to use the 
> faster execution
> plan.

It would be a bit easier to diagnose the problem if you posted EXPLAIN
ANALYZE rather than just EXPLAIN.  The two plans you posted looked very
similar except for the order of the nested loop in subquery 1 and an index
scan rather than a seq scan in subquery 2.  

My guess would be that the order of the nested loop is determined mostly by
estimates of matching rows.  If you ran an EXPLAIN ANALYZE you could tell if
the planner is estimating correctly.  If it is not, you could try increasing
your statistics target and running ANALYZE.  

To make the planner prefer an index scan over a seq scan, I would first
check the statistics again, and then you can try setting enable_seqscan to
false (enable_seqscan is meant more for testing than production) or, you
could try reducing random_page_cost, but you should test that against a
range of queries before putting it in production.

Dave


---(end of broadcast)---
TIP 3: Have you checked our extensive FAQ?

   http://www.postgresql.org/docs/faq


Re: [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Alan Hodgson
On Wednesday 27 September 2006 09:08, Edoardo Ceccarelli <[EMAIL PROTECTED]> 
wrote:
>
> How can I configure the vacuum to run after the daily batch
> insert/update?
>

If you really only want it to run then, you should disable autovacuum and 
continue to run the vacuum manually.

You might also investigate the vacuum cost delay options, which will make 
vacuum take longer but will have less of an impact on your database while 
running.


-- 
"If a nation values anything more than freedom, it will lose its freedom;
and the irony of it is that if it is comfort or money that it values more,
it will lose that too." -- Somerset Maugham, Author


---(end of broadcast)---
TIP 3: Have you checked our extensive FAQ?

   http://www.postgresql.org/docs/faq


Re: [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Edoardo Ceccarelli






Bill Moran wrote:

  In response to Edoardo Ceccarelli <[EMAIL PROTECTED]>:
  


I have read that autovacuum cannot check to see pg load before launching 
vacuum but is there any patch about it? that would sort out the problem 
in a good and simple way.
Otherwise, which kind of set of parameters I should put in autovacuum 
configuration? I am stuck because in our case the table gets mostly read 
and if I set up things as to vacuum the table after a specific amount of 
insert/updates, I cannot foresee whether this could happen during 
daytime when server is under high load.
How can I configure the vacuum to run after the daily batch insert/update?

  
  
It doesn't sound as if your setup is a good match for autovacuum.  You
might be better off going back to the cron vacuums.  That's the
beauty of Postgres -- it gives you the choice.

If you want to continue with autovac, you may want to experiment with
vacuum_cost_delay and associated parameters, which can lessen the
impact of vacuuming.

  

The db is constantly monitored during high peak so that we can switch
to a backup pg7.3 database that is being vacuumed every night.
This is giving me the opportunity to try it so I tried this:

vacuum_cost_delay = 200
vacuum_cost_page_hit = 5
vacuum_cost_page_miss = 10
vacuum_cost_page_dirty = 20
vacuum_cost_limit = 100

I know these values affect the normal vacuum process but apparently
this means setting
#autovacuum_vacuum_cost_delay = -1  # default vacuum cost delay for
    # autovac, -1 means use
    # vacuum_cost_delay

and 
#autovacuum_vacuum_cost_limit = -1  # default vacuum cost limit for
    # autovac, -1 means use
    # vacuum_cost_limit


for the rest of them I am currently trying the deafults:

#autovacuum_naptime = 60    # time between autovacuum runs,
in secs
#autovacuum_vacuum_threshold = 1000 # min # of tuple updates before
vacuum
#autovacuum_analyze_threshold = 500 # min # of tuple updates before
analyze
#autovacuum_vacuum_scale_factor = 0.4   # fraction of rel size before
vacuum
#autovacuum_analyze_scale_factor = 0.2  # fraction of rel size before
analyze

Does anybody know which process is actually AUTO-vacuum-ing the db? 
So that I can check when is running...








Re: [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Edoardo Ceccarelli




Rod Taylor wrote:

  On Wed, 2006-09-27 at 18:08 +0200, Edoardo Ceccarelli wrote:
  
  
I have read that autovacuum cannot check to see pg load before
launching 
vacuum but is there any patch about it? that would sort out the
problem 
in a good and simple way. 

  
  
In some cases the solution to high load is to vacuum the tables being
hit the heaviest -- meaning that simply checking machine load isn't
enough to make that decision.

In fact, that high load problem is exactly why autovacuum was created in
the first place.
  

True, 
but autovacuum could check load -before- and -during- it's execution
and it could adjust himself automatically to perform more or less
aggressively depending on the difference between those two values.
Maybe with a parameter like: maximum-autovacuum-load=0.2
that would mean: "never load the machine more than 20% for the
autovacuum"

...another thing is, how could autovacuum check for machine load, this
is something I cannot imagine right now...





Re: [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Tobias Brox
[Edoardo Ceccarelli - Wed at 06:49:23PM +0200]
> ...another thing is, how could autovacuum check for machine load, this 
> is something I cannot imagine right now...

One solution I made for our application, is to check the
pg_stats_activity view.  It requires some config to get the stats
available in that view, though.  When the application is to start a
low-priority transaction, it will first do:

  select count(*) from pg_stat_activity where current_query not like
  '

[PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Edoardo Ceccarelli

Hello,

we are running a 7.3 postgres db with only a big table (avg 
500.000records) and 7 indexes for a search engine.

we have 2 of this databases and we can switch from one to another.
Last week we decided to give a try to 8.1 on one of them and everything 
went fine, db is faster (about 2 or 3 times in our case) and the server 
load is higher - which should mean that faster response time is achieved 
by taking a better use of the server.


We also activated the autovacuum feature to give it a try and that's 
were our problems started.
I left the standard autovacuum configuration just to wait and see, pg 
decided to start a vacuum on the table just midday when users were 
launching search queries on the table and server load reached a very 
high value so that in a couple of minutes the db was unusable


With pg7.3 we use to vacuum the db night time, mostly because the insert 
and updates in this table is made in a batch way: a single task that 
puts 100.000 records in the db in 10/20minutes, so the best time to 
actually vacuum the db would be after this batch.


I have read that autovacuum cannot check to see pg load before launching 
vacuum but is there any patch about it? that would sort out the problem 
in a good and simple way.
Otherwise, which kind of set of parameters I should put in autovacuum 
configuration? I am stuck because in our case the table gets mostly read 
and if I set up things as to vacuum the table after a specific amount of 
insert/updates, I cannot foresee whether this could happen during 
daytime when server is under high load.

How can I configure the vacuum to run after the daily batch insert/update?

Any help appreciated
Thank you very much
Edoardo



---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Tobias Brox
[Edoardo Ceccarelli - Wed at 06:08:30PM +0200]
> We also activated the autovacuum feature to give it a try and that's 
> were our problems started.
(...)
> How can I configure the vacuum to run after the daily batch insert/update?

I think you shouldn't use autovacuum in your case.

We haven't dared testing out autovacuum yet even though we probably
should, so we're running vacuum at fixed times of the day.  We have a
very simple script to do this, the most important part of it reads:

echo "vacuum verbose analyze;" | psql $DB_NAME > $logdir/$filename 2>&1


---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Csaba Nagy
On Wed, 2006-09-27 at 18:08, Edoardo Ceccarelli wrote:
> How can I configure the vacuum to run after the daily batch insert/update?

Check out this:
http://www.postgresql.org/docs/8.1/static/catalog-pg-autovacuum.html

By inserting the right row you can disable autovacuum to vacuum your big
tables, and then you can schedule vacuum nightly for those just as
before. There's still a benefit in that you don't need to care about
vacuuming the rest of the tables, which will be done just in time.

Cheers,
Csaba.


---(end of broadcast)---
TIP 5: don't forget to increase your free space map settings


Re: [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Bill Moran
In response to Edoardo Ceccarelli <[EMAIL PROTECTED]>:

> Hello,
> 
> we are running a 7.3 postgres db with only a big table (avg 
> 500.000records) and 7 indexes for a search engine.
> we have 2 of this databases and we can switch from one to another.
> Last week we decided to give a try to 8.1 on one of them and everything 
> went fine, db is faster (about 2 or 3 times in our case) and the server 
> load is higher - which should mean that faster response time is achieved 
> by taking a better use of the server.
> 
> We also activated the autovacuum feature to give it a try and that's 
> were our problems started.
> I left the standard autovacuum configuration just to wait and see, pg 
> decided to start a vacuum on the table just midday when users were 
> launching search queries on the table and server load reached a very 
> high value so that in a couple of minutes the db was unusable
> 
> With pg7.3 we use to vacuum the db night time, mostly because the insert 
> and updates in this table is made in a batch way: a single task that 
> puts 100.000 records in the db in 10/20minutes, so the best time to 
> actually vacuum the db would be after this batch.
> 
> I have read that autovacuum cannot check to see pg load before launching 
> vacuum but is there any patch about it? that would sort out the problem 
> in a good and simple way.
> Otherwise, which kind of set of parameters I should put in autovacuum 
> configuration? I am stuck because in our case the table gets mostly read 
> and if I set up things as to vacuum the table after a specific amount of 
> insert/updates, I cannot foresee whether this could happen during 
> daytime when server is under high load.
> How can I configure the vacuum to run after the daily batch insert/update?

It doesn't sound as if your setup is a good match for autovacuum.  You
might be better off going back to the cron vacuums.  That's the
beauty of Postgres -- it gives you the choice.

If you want to continue with autovac, you may want to experiment with
vacuum_cost_delay and associated parameters, which can lessen the
impact of vacuuming.

-- 
Bill Moran
Collaborative Fusion Inc.

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Rod Taylor
On Wed, 2006-09-27 at 18:08 +0200, Edoardo Ceccarelli wrote:
> 
> I have read that autovacuum cannot check to see pg load before
> launching 
> vacuum but is there any patch about it? that would sort out the
> problem 
> in a good and simple way. 

In some cases the solution to high load is to vacuum the tables being
hit the heaviest -- meaning that simply checking machine load isn't
enough to make that decision.

In fact, that high load problem is exactly why autovacuum was created in
the first place.
-- 


---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


Re: [ADMIN] [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Matthew T. O'Connor

Csaba Nagy wrote:

On Wed, 2006-09-27 at 18:08, Edoardo Ceccarelli wrote:
  

How can I configure the vacuum to run after the daily batch insert/update?



Check out this:
http://www.postgresql.org/docs/8.1/static/catalog-pg-autovacuum.html

By inserting the right row you can disable autovacuum to vacuum your big
tables, and then you can schedule vacuum nightly for those just as
before. There's still a benefit in that you don't need to care about
vacuuming the rest of the tables, which will be done just in time.


In addition autovacuum respects the work of manual or cron based 
vacuums, so if you issue a vacuum right after a daily batch insert / 
update, autovacuum won't repeat the work of that manual vacuum.




---(end of broadcast)---
TIP 3: Have you checked our extensive FAQ?

  http://www.postgresql.org/docs/faq


[PERFORM] Problems with inconsistant query performance.

2006-09-27 Thread Matthew Schumacher
List,

I posted a little about this a while back to the general list, but never
really got any where with it so I'll try again, this time with a little
more detail and hopefully someone can send me in the right direction.

Here is the problem, I have a procedure that is called 100k times a day.
 Most of the time it's screaming fast, but other times it takes a few
seconds.  When it does lag my machine can get behind which causes other
problems, so I'm trying to figure out why there is such a huge delta in
performance with this proc.

The proc is pretty large (due to the number of vars) so I will summarize
it here:

==
CREATE acctmessage(  )RETURNS void AS $$
BEGIN
INSERT into tmpaccounting_tab ( ... ) values ( ... );

IF _acctType = 'start' THEN
  BEGIN
  INSERT into radutmp_tab ( ... ) valuse ( ... );
  EXCEPTION WHEN UNIQUE_VIOLATION THEN
NULL;
  END;
ELSIF _acctType = 'stop' THEN
  UPDATE radutmp_tab SET ... WHERE sessionId = _sessionId AND userName =
_userName;
  IF (NOT FOUND) THEN
INSERT into radutmp_tab ( ... ) values ( ... );
  END IF;

END IF;
END;
$$
LANGUAGE plpgsql;
==

So in a nutshell, if I get an accounting record put it in the
tmpaccounting_tab and then insert or update the radutmp_tab based on
what kind of record it is.  If for some reason the message is a start
message and a duplicate, drop it, and if the message is a stop message
and we don't have the start then insert it.

The tmpaccounting_tab table doesn't have any indexes and gets flushed to
the accounting_tab table nightly so it should have very good insert
performance as the table is kept small (compared to accounting_tab) and
doesn't have index overhead.  The radutmp_tab is also kept small as
completed sessions are flushed to another table nightly, but I do keep
an index on sessionId and userName so the update isn't slow.

Now that you have the layout, the problem: I log whenever a query takes
more than 250ms and have logged this query:

duration: 3549.229 ms  statement: select acctMessage( 'stop',
'username', 'address', 'time', 'session', 'port', 'address', 'bytes',
'bytes', 0, 0, 1, 'reason', '', '', '', 'proto', 'service',  'info')

But when I go do an explain analyze it is very fast:

 QUERY PLAN

 Result  (cost=0.00..0.03 rows=1 width=0) (actual time=6.812..6.813
rows=1 loops=1)
 Total runtime: 6.888 ms

So the question is why on a relatively simple proc and I getting a query
performance delta between 3549ms and 7ms?

Here are some values from my postgres.conf to look at:

shared_buffers = 6  # min 16 or max_connections*2,
8KB each
temp_buffers = 5000 # min 100, 8KB each
#max_prepared_transactions = 5  # can be 0 or more
# note: increasing max_prepared_transactions costs ~600 bytes of shared
memory
# per transaction slot, plus lock space (see max_locks_per_transaction).
work_mem = 131072   # min 64, size in KB
maintenance_work_mem = 262144   # min 1024, size in KB
max_stack_depth = 2048  # min 100, size in KB
effective_cache_size = 65536# typically 8KB each


Thanks for any help you can give,
schu


---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [PERFORM] Merge Join vs Nested Loop

2006-09-27 Thread Tobias Brox
I found a way to survive yet some more weeks :-)

One of the queries we've had most problems with today is principially
something like:

  select A.*,sum(B.*) from A join B where A.created>x and ... order by
  A.created desc limit 32 group by A.*

There is by average two rows in B for every row in A.
Note the 'limit 32'-part.  I rewrote the query to:

  select A.*,(select sum(B.*) from B ...) where A.created>x and ...
  order by A.created desc limit 32;

And voila, the planner found out it needed just some few rows from A,
and execution time was cutted from 1-2 minutes down to 20 ms. :-)

I've also started thinking a bit harder about table partitioning, if we
add some more redundancy both to the queries and the database, it may
help us drastically reduce the real expenses of some of the merge
joins...


---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [PERFORM] Forcing the use of particular execution plans

2006-09-27 Thread Jim C. Nasby
On Wed, Sep 27, 2006 at 10:51:26AM -0500, Dave Dutcher wrote:
> To make the planner prefer an index scan over a seq scan, I would first
> check the statistics again, and then you can try setting enable_seqscan to
> false (enable_seqscan is meant more for testing than production) or, you
> could try reducing random_page_cost, but you should test that against a
> range of queries before putting it in production.

Index scans are also pretty picky about correlation. If you have really
low correlation you don't want to index scan, but I think our current
estimates make it too eager to switch to a seqscan.
-- 
Jim Nasby[EMAIL PROTECTED]
EnterpriseDB  http://enterprisedb.com  512.569.9461 (cell)

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [PERFORM] autovacuum on a -mostly- r/o table

2006-09-27 Thread Bill Moran
In response to Edoardo Ceccarelli <[EMAIL PROTECTED]>:

> Rod Taylor wrote:
> > On Wed, 2006-09-27 at 18:08 +0200, Edoardo Ceccarelli wrote:
> >   
> >> I have read that autovacuum cannot check to see pg load before
> >> launching 
> >> vacuum but is there any patch about it? that would sort out the
> >> problem 
> >> in a good and simple way. 
> >> 
> >
> > In some cases the solution to high load is to vacuum the tables being
> > hit the heaviest -- meaning that simply checking machine load isn't
> > enough to make that decision.
> >
> > In fact, that high load problem is exactly why autovacuum was created in
> > the first place.
> >   
> True,
> but autovacuum could check load -before- and -during- it's execution and 
> it could adjust himself automatically to perform more or less 
> aggressively depending on the difference between those two values.
> Maybe with a parameter like: maximum-autovacuum-load=0.2
> that would mean: "never load the machine more than 20% for the autovacuum"

This is pretty non-trivial.  How do you define 20% load?  20% of the
CPU?  Does that mean that it's OK for autovac to use 3% cpu and 100% of
your IO?  Ok, so we need to calculate an average of IO and CPU -- which
disks?  If your WAL logs are on one disk, and you've used tablespaces
to spread the rest of your DB across different partitions, it can
be pretty difficult to determine which IO parameters you want to take
into consideration.

-- 
Bill Moran
Collaborative Fusion Inc.


IMPORTANT: This message contains confidential information and is
intended only for the individual named. If the reader of this
message is not an intended recipient (or the individual
responsible for the delivery of this message to an intended
recipient), please be advised that any re-use, dissemination,
distribution or copying of this message is prohibited. Please
notify the sender immediately by e-mail if you have received
this e-mail by mistake and delete this e-mail from your system.
E-mail transmission cannot be guaranteed to be secure or
error-free as information could be intercepted, corrupted, lost,
destroyed, arrive late or incomplete, or contain viruses. The
sender therefore does not accept liability for any errors or
omissions in the contents of this message, which arise as a
result of e-mail transmission.


---(end of broadcast)---
TIP 3: Have you checked our extensive FAQ?

   http://www.postgresql.org/docs/faq


Re: [PERFORM] Problems with inconsistant query performance.

2006-09-27 Thread Jim C. Nasby
Periodically taking longer is probably a case of some other process in
the database holding a lock you need, or otherwise bogging the system
down, especially if you're always running acctmessage from the same
connection (because the query plans shouldn't be changing then). I'd
suggest looking at what else is happening at the same time.

Also, it's more efficient to operate on chunks of data rather than one
row at a time whenever possible. If you have to log each row
individually, consider simply logging them into a table, and then
periodically pulling data out of that table to do additional processing
on it.

BTW, your detection of duplicates/row existance has a race condition.
Take a look at example 36-1 at
http://www.postgresql.org/docs/8.1/interactive/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING
for a better way to handle it.

On Wed, Sep 27, 2006 at 10:37:22AM -0800, Matthew Schumacher wrote:
> List,
> 
> I posted a little about this a while back to the general list, but never
> really got any where with it so I'll try again, this time with a little
> more detail and hopefully someone can send me in the right direction.
> 
> Here is the problem, I have a procedure that is called 100k times a day.
>  Most of the time it's screaming fast, but other times it takes a few
> seconds.  When it does lag my machine can get behind which causes other
> problems, so I'm trying to figure out why there is such a huge delta in
> performance with this proc.
> 
> The proc is pretty large (due to the number of vars) so I will summarize
> it here:
> 
> ==
> CREATE acctmessage(  )RETURNS void AS $$
> BEGIN
> INSERT into tmpaccounting_tab ( ... ) values ( ... );
> 
> IF _acctType = 'start' THEN
>   BEGIN
>   INSERT into radutmp_tab ( ... ) valuse ( ... );
>   EXCEPTION WHEN UNIQUE_VIOLATION THEN
> NULL;
>   END;
> ELSIF _acctType = 'stop' THEN
>   UPDATE radutmp_tab SET ... WHERE sessionId = _sessionId AND userName =
> _userName;
>   IF (NOT FOUND) THEN
> INSERT into radutmp_tab ( ... ) values ( ... );
>   END IF;
> 
> END IF;
> END;
> $$
> LANGUAGE plpgsql;
> ==
> 
> So in a nutshell, if I get an accounting record put it in the
> tmpaccounting_tab and then insert or update the radutmp_tab based on
> what kind of record it is.  If for some reason the message is a start
> message and a duplicate, drop it, and if the message is a stop message
> and we don't have the start then insert it.
> 
> The tmpaccounting_tab table doesn't have any indexes and gets flushed to
> the accounting_tab table nightly so it should have very good insert
> performance as the table is kept small (compared to accounting_tab) and
> doesn't have index overhead.  The radutmp_tab is also kept small as
> completed sessions are flushed to another table nightly, but I do keep
> an index on sessionId and userName so the update isn't slow.
> 
> Now that you have the layout, the problem: I log whenever a query takes
> more than 250ms and have logged this query:
> 
> duration: 3549.229 ms  statement: select acctMessage( 'stop',
> 'username', 'address', 'time', 'session', 'port', 'address', 'bytes',
> 'bytes', 0, 0, 1, 'reason', '', '', '', 'proto', 'service',  'info')
> 
> But when I go do an explain analyze it is very fast:
> 
>  QUERY PLAN
> 
>  Result  (cost=0.00..0.03 rows=1 width=0) (actual time=6.812..6.813
> rows=1 loops=1)
>  Total runtime: 6.888 ms
> 
> So the question is why on a relatively simple proc and I getting a query
> performance delta between 3549ms and 7ms?
> 
> Here are some values from my postgres.conf to look at:
> 
> shared_buffers = 6  # min 16 or max_connections*2,
> 8KB each
> temp_buffers = 5000 # min 100, 8KB each
> #max_prepared_transactions = 5  # can be 0 or more
> # note: increasing max_prepared_transactions costs ~600 bytes of shared
> memory
> # per transaction slot, plus lock space (see max_locks_per_transaction).
> work_mem = 131072   # min 64, size in KB
> maintenance_work_mem = 262144   # min 1024, size in KB
> max_stack_depth = 2048  # min 100, size in KB
> effective_cache_size = 65536# typically 8KB each
> 
> 
> Thanks for any help you can give,
> schu
> 
> 
> ---(end of broadcast)---
> TIP 6: explain analyze is your friend
> 

-- 
Jim Nasby[EMAIL PROTECTED]
EnterpriseDB  http://enterprisedb.com  512.569.9461 (cell)

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can ge

Re: [PERFORM] Problems with inconsistant query performance.

2006-09-27 Thread Matthew Schumacher
Jim,

Thanks for the help.  I went and looked at that example and I don't see
how it's different than the "INSERT into radutmp_tab" I'm already doing.
 Both raise an exception, the only difference is that I'm not doing
anything with it.  Perhaps you are talking about the "IF (NOT FOUND)" I
put after the "UPDATE radutmp_tab".  Should this be an EXCEPTION
instead?  Also I don't know how this could cause a race condition.  As
far as I understand each proc is run in it's own transaction, and the
code in the proc is run serially.  Can you explain more why this could
case a race?

Thanks,
schu



Jim C. Nasby wrote:
> Periodically taking longer is probably a case of some other process in
> the database holding a lock you need, or otherwise bogging the system
> down, especially if you're always running acctmessage from the same
> connection (because the query plans shouldn't be changing then). I'd
> suggest looking at what else is happening at the same time.
> 
> Also, it's more efficient to operate on chunks of data rather than one
> row at a time whenever possible. If you have to log each row
> individually, consider simply logging them into a table, and then
> periodically pulling data out of that table to do additional processing
> on it.
> 
> BTW, your detection of duplicates/row existance has a race condition.
> Take a look at example 36-1 at
> http://www.postgresql.org/docs/8.1/interactive/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING
> for a better way to handle it.

>> ==
>> CREATE acctmessage(  )RETURNS void AS $$
>> BEGIN
>> INSERT into tmpaccounting_tab ( ... ) values ( ... );
>>
>> IF _acctType = 'start' THEN
>>   BEGIN
>>   INSERT into radutmp_tab ( ... ) valuse ( ... );
>>   EXCEPTION WHEN UNIQUE_VIOLATION THEN
>> NULL;
>>   END;
>> ELSIF _acctType = 'stop' THEN
>>   UPDATE radutmp_tab SET ... WHERE sessionId = _sessionId AND userName =
>> _userName;
>>   IF (NOT FOUND) THEN
>> INSERT into radutmp_tab ( ... ) values ( ... );
>>   END IF;
>>
>> END IF;
>> END;
>> $$
>> LANGUAGE plpgsql;
>> ==

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [PERFORM] Problems with inconsistant query performance.

2006-09-27 Thread Jim C. Nasby
On Wed, Sep 27, 2006 at 01:33:09PM -0800, Matthew Schumacher wrote:
> Jim,
> 
> Thanks for the help.  I went and looked at that example and I don't see
> how it's different than the "INSERT into radutmp_tab" I'm already doing.
>  Both raise an exception, the only difference is that I'm not doing
> anything with it.  Perhaps you are talking about the "IF (NOT FOUND)" I
> put after the "UPDATE radutmp_tab".  Should this be an EXCEPTION
> instead?  Also I don't know how this could cause a race condition.  As
> far as I understand each proc is run in it's own transaction, and the
> code in the proc is run serially.  Can you explain more why this could
> case a race?
 
It can cause a race if another process could be performing those same
inserts or updates at the same time.

I know the UPDATE case can certainly cause a race. 2 connections try to
update, both hit NOT FOUND, both try to insert... only one will get to
commit.

I think that the UNIQUE_VIOLATION case should be safe, since a second
inserter should block if there's another insert that's waiting to
commit.

DELETEs are something else to think about for both cases.

If you're certain that only one process will be performing DML on those
tables at any given time, then what you have is safe. But if that's the
case, I'm thinking you should be able to group things into chunks, which
should be more efficient.

> Thanks,
> schu
> 
> 
> 
> Jim C. Nasby wrote:
> > Periodically taking longer is probably a case of some other process in
> > the database holding a lock you need, or otherwise bogging the system
> > down, especially if you're always running acctmessage from the same
> > connection (because the query plans shouldn't be changing then). I'd
> > suggest looking at what else is happening at the same time.
> > 
> > Also, it's more efficient to operate on chunks of data rather than one
> > row at a time whenever possible. If you have to log each row
> > individually, consider simply logging them into a table, and then
> > periodically pulling data out of that table to do additional processing
> > on it.
> > 
> > BTW, your detection of duplicates/row existance has a race condition.
> > Take a look at example 36-1 at
> > http://www.postgresql.org/docs/8.1/interactive/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING
> > for a better way to handle it.
> 
> >> ==
> >> CREATE acctmessage(  )RETURNS void AS $$
> >> BEGIN
> >> INSERT into tmpaccounting_tab ( ... ) values ( ... );
> >>
> >> IF _acctType = 'start' THEN
> >>   BEGIN
> >>   INSERT into radutmp_tab ( ... ) valuse ( ... );
> >>   EXCEPTION WHEN UNIQUE_VIOLATION THEN
> >> NULL;
> >>   END;
> >> ELSIF _acctType = 'stop' THEN
> >>   UPDATE radutmp_tab SET ... WHERE sessionId = _sessionId AND userName =
> >> _userName;
> >>   IF (NOT FOUND) THEN
> >> INSERT into radutmp_tab ( ... ) values ( ... );
> >>   END IF;
> >>
> >> END IF;
> >> END;
> >> $$
> >> LANGUAGE plpgsql;
> >> ==
> 

-- 
Jim Nasby[EMAIL PROTECTED]
EnterpriseDB  http://enterprisedb.com  512.569.9461 (cell)

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


Re: [PERFORM] Problems with inconsistant query performance.

2006-09-27 Thread Matthew Schumacher
Jim C. Nasby wrote:
>  
> It can cause a race if another process could be performing those same
> inserts or updates at the same time.

There are inserts and updates running all of the time, but never the
same data.  I'm not sure how I can get around this since the queries are
coming from my radius system which is not able to queue this stuff up
because it waits for a successful query before returning an OK packet
back to the client.

> 
> I know the UPDATE case can certainly cause a race. 2 connections try to
> update, both hit NOT FOUND, both try to insert... only one will get to
> commit.

Why is that?  Doesn't the first update lock the row causing the second
one to wait, then the second one stomps on the row allowing both to
commit?  I must be confused

> 
> I think that the UNIQUE_VIOLATION case should be safe, since a second
> inserter should block if there's another insert that's waiting to
> commit.

Are you saying that inserts inside of an EXCEPTION block, but normal
inserts don't?

> 
> DELETEs are something else to think about for both cases.

I only do one delete and that is every night when I move the data to the
primary table and remove that days worth of data from the tmp table.
This is done at non-peak times with a vacuum, so I think I'm good here.

> 
> If you're certain that only one process will be performing DML on those
> tables at any given time, then what you have is safe. But if that's the
> case, I'm thinking you should be able to group things into chunks, which
> should be more efficient.

Yea, I wish I could, but I really need to do one at a time because of
how radius waits for a successful query before telling the access server
all is well.  If the query fails, the access server won't get the 'OK'
packet and will send the data to the secondary radius system where it
gets queued.

Do you know of a way to see what is going on with the locking system
other than "select * from pg_locks"?  I can't ever seem to catch the
system when queries start to lag.

Thanks again,
schu

---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [PERFORM] Problems with inconsistant query performance.

2006-09-27 Thread Jim C. Nasby
On Wed, Sep 27, 2006 at 02:17:23PM -0800, Matthew Schumacher wrote:
> Jim C. Nasby wrote:
> >  
> > It can cause a race if another process could be performing those same
> > inserts or updates at the same time.
> 
> There are inserts and updates running all of the time, but never the
> same data.  I'm not sure how I can get around this since the queries are
> coming from my radius system which is not able to queue this stuff up
> because it waits for a successful query before returning an OK packet
> back to the client.
> 
> > 
> > I know the UPDATE case can certainly cause a race. 2 connections try to
> > update, both hit NOT FOUND, both try to insert... only one will get to
> > commit.
> 
> Why is that?  Doesn't the first update lock the row causing the second
> one to wait, then the second one stomps on the row allowing both to
> commit?  I must be confused

What if there's no row to update?

Process A   Process B
UPDATE .. NOT FOUND
UPDATE .. NOT FOUND
INSERT
INSERT blocks
COMMIT
UNIQUE_VIOLATION

That's assuming that there's a unique index. If there isn't one, you'd
get duplicate records.

> > I think that the UNIQUE_VIOLATION case should be safe, since a second
> > inserter should block if there's another insert that's waiting to
> > commit.
> 
> Are you saying that inserts inside of an EXCEPTION block, but normal
> inserts don't?

No... if there's a unique index, a second INSERT attempting to create a
duplicate record will block until the first INSERT etiher commits or
rollsback.

> > DELETEs are something else to think about for both cases.
> 
> I only do one delete and that is every night when I move the data to the
> primary table and remove that days worth of data from the tmp table.
> This is done at non-peak times with a vacuum, so I think I'm good here.

Except that you might still have someone fire off that function while
the delete's running, or vice-versa. So there could be a race condition
(I haven't thought enough about what race conditions that could cause).

> > If you're certain that only one process will be performing DML on those
> > tables at any given time, then what you have is safe. But if that's the
> > case, I'm thinking you should be able to group things into chunks, which
> > should be more efficient.
> 
> Yea, I wish I could, but I really need to do one at a time because of
> how radius waits for a successful query before telling the access server
> all is well.  If the query fails, the access server won't get the 'OK'
> packet and will send the data to the secondary radius system where it
> gets queued.
 
In that case, the key is to do the absolute smallest amount of work
possible as part of that transaction. Ideally, you would only insert a
record into a queue table somewhere, and then periodically process
records out of that table in batches.

> Do you know of a way to see what is going on with the locking system
> other than "select * from pg_locks"?  I can't ever seem to catch the
> system when queries start to lag.

No. Your best bet is to open two psql sessions and step through things
in different combinations (make sure and do this in transactions).
-- 
Jim Nasby[EMAIL PROTECTED]
EnterpriseDB  http://enterprisedb.com  512.569.9461 (cell)

---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match


[PERFORM] slow queue-like empty table

2006-09-27 Thread Tobias Brox
I have a query which really should be lightning fast (limit 1 from
index), but which isn't.  I've checked the pg_locks table, there are no
locks on the table.  The database is not under heavy load at the moment,
but the query seems to draw CPU power.  I checked the pg_locks view, but
found nothing locking the table.  It's a queue-like table, lots of rows
beeing added and removed to the queue.  The queue is currently empty.
Have a look:

NBET=> vacuum verbose analyze my_queue;
INFO:  vacuuming "public.my_queue"
INFO:  index "my_queue_pkey" now contains 34058 row
versions in 390 pages
DETAIL:  288 index pages have been deleted, 285 are current
ly reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "my_queue": found 0 removable, 34058 nonremovable row versions in 185 
pages
DETAIL:  34058 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.my_queue"
INFO:  "my_queue": scanned 185 of 185 pages, containing 0 live rows and 34058 
dead rows; 0 rows in sample, 0 estimated total rows
VACUUM
NBET=> explain analyze select bet_id from my_queue order by bet_id limit 1;
  QUERY 
PLAN  
---
 Limit  (cost=0.00..0.04 rows=1 width=4) (actual time=402.525..402.525 rows=0 
loops=1)
   ->  Index Scan using my_queue_pkey on stats_bet_queue  (cost=0.00..1314.71 
rows=34058 width=4) (actual time=402.518..402.518 rows=0 loops=1)
 Total runtime: 402.560 ms
(3 rows)

NBET=> select count(*) from my_queue;
 count
---
 0
(1 row)

It really seems like some transaction is still viewing the queue, since
it found 38k of non-removable rows ... but how do I find the pid of the
transaction viewing the queue?  As said, the pg_locks didn't give me any
hints ...


---(end of broadcast)---
TIP 6: explain analyze is your friend