Re: [PERFORM] Databases vs Schemas

2009-10-10 Thread Chris Kratz
On Fri, Oct 9, 2009 at 11:11 PM, Tom Lane t...@sss.pgh.pa.us wrote:

 Scott Carey sc...@richrelevance.com writes:
  I've got 200,000 tables in one db (8.4), and some tools barely work.  The
  system catalogs get inefficient when large and psql especially has
 trouble.
  Tab completion takes forever, even if I make a schema s with one table
 in
  it and type s. and try and tab complete -- its as if its scanning all
  without a schema qualifier or using an index.

 The tab-completion queries have never been vetted for performance
 particularly :-(

 Just out of curiosity, how much does this help?

 alter function pg_table_is_visible(oid) cost 10;

 (You'll need to do it as superuser --- if it makes things worse, just
 set the cost back to 1.)

  Sometimes it does not match
  valid tables at all, and sometimes regex matching fails too ('\dt
  schema.*_*_*' intermittently flakes out if it returns a lot of matches).

 There are some arbitrary LIMIT 1000 clauses in those queries, which
 probably explains this ... but taking them out would likely cause
 libreadline to get indigestion ...

regards, tom lane


We ran into this exact situation with a pg 8.3 database and a very large
number of tables.  psql would wait for 20 to 30 seconds if the user was
unlucky enough to hit the tab key.  After doing some research with query
logging, explain analyze and some trial and error, we came to the same
conclusion.  Altering the cost for the pg_table_is_visible function to 10
fixed our performance problem immediately.  It appears that when the cost
was set to 1, that the query optimizer first ran the function over the
entire pg_class table.  By increasing the cost, it now only runs the
function over the rows returned by the other items in the where clause.

-chris


Re: [PERFORM] Incorrect estimates on correlated filters

2008-08-13 Thread Chris Kratz
On Wed, Aug 13, 2008 at 10:59 AM, Decibel! [EMAIL PROTECTED] wrote:

 On Aug 12, 2008, at 4:59 PM, Chris Kratz wrote:

 Ran into a re-occuring performance problem with some report queries again
 today.  In a nutshell, we have filters on either multiple joined tables, or
 multiple columns on a single table that are highly correlated.  So, the
 estimates come out grossly incorrect (the planner has no way to know they
 are correlated).  2000:1 for one I'm looking at right now.  Generally this
 doesn't matter, except in complex reporting queries like these when this is
 the first join of 40 other joins.  Because the estimate is wrong at the
 lowest level, it snowballs up through the rest of the joins causing the
 query to run very, very slowly.   In many of these cases, forcing nested
 loops off for the duration of the query fixes the problem.  But I have a
 couple that still are painfully slow and shouldn't be.

 I've been reading through the archives with others having similar problems
 (including myself a year ago).  Am I right in assuming that at this point
 there is still little we can do in postgres to speed up this kind of query?
  Right now the planner has no way to know the correlation between different
 columns in the same table, let alone columns in different tables.  So, it
 just assumes no correlation and returns incorrectly low estimates in cases
 like these.

 The only solution I've come up with so far is to materialize portions of
 the larger query into subqueries with these correlated filters which are
 indexed and analyzed before joining into the larger query.  This would keep
 the incorrect estimates from snowballing up through the chain of joins.

 Are there any other solutions to this problem?



 Well... you could try and convince certain members of the community that we
 actually do need some kind of a query hint mechanism... ;)

 I did make a suggestion a few months ago that involved sorting a table on
 different columns and recording the correlation of other columns. The scheme
 isn't perfect, but it would help detect cases like a field populated by a
 sequence and another field that's insert timestamp; those two fields would
 correlate highly, and you should even be able to correlate the two
 histograms; that would allow you to infer that most of the insert times for
 _id's between 100 and 200 will be between 2008-01-01 00:10 and 2008-01-01
 00:20, for example.
 --
 Decibel!, aka Jim C. Nasby, Database Architect  [EMAIL PROTECTED]
 Give your computer some brain candy! www.distributed.net Team #1828


 Thanks for the reply,

Yes, I know hints are frowned upon around here.  Though, I'd love to have
them or something equivalent on this particular query just so the customer
can run their important reports.  As it is, it's unrunnable.

Unfortunately, if I don't think the sorting idea would help in the one case
I'm looking at which involves filters on two tables that are joined
together.  The filters happen to be correlated such that about 95% of the
rows from each filtered table are actually returned after the join.
Unfortunately, the planner thinks we will get 1 row back.

I do have to find a way to make these queries runnable.  I'll keep looking.

Thanks,

-Chris


[PERFORM] Incorrect estimates on correlated filters

2008-08-12 Thread Chris Kratz
Hello All,

Ran into a re-occuring performance problem with some report queries again
today.  In a nutshell, we have filters on either multiple joined tables, or
multiple columns on a single table that are highly correlated.  So, the
estimates come out grossly incorrect (the planner has no way to know they
are correlated).  2000:1 for one I'm looking at right now.  Generally this
doesn't matter, except in complex reporting queries like these when this is
the first join of 40 other joins.  Because the estimate is wrong at the
lowest level, it snowballs up through the rest of the joins causing the
query to run very, very slowly.   In many of these cases, forcing nested
loops off for the duration of the query fixes the problem.  But I have a
couple that still are painfully slow and shouldn't be.

I've been reading through the archives with others having similar problems
(including myself a year ago).  Am I right in assuming that at this point
there is still little we can do in postgres to speed up this kind of query?
Right now the planner has no way to know the correlation between different
columns in the same table, let alone columns in different tables.  So, it
just assumes no correlation and returns incorrectly low estimates in cases
like these.

The only solution I've come up with so far is to materialize portions of the
larger query into subqueries with these correlated filters which are indexed
and analyzed before joining into the larger query.  This would keep the
incorrect estimates from snowballing up through the chain of joins.

Are there any other solutions to this problem?

Thanks,

-Chris


[PERFORM] Planner mis-estimation using nested loops followup

2008-03-18 Thread Chris Kratz
A number of weeks ago, I had posted a request for help regarding join
estimates in pg 8.2.6.  In moderately complex to very complex ad hoc queries
in our system, we were consistently having the system massively
underestimate the number of rows coming out of join at a low level making
these queries very slow and inefficient.  At times the mis-estimation was
1000:1.  Ie when it should have been 2000 returned rows from a join, the
planner assumed 1 or 2 rows.  Modifying stats on the join columns up to the
max made little difference (y, we analyzed tables in question after each
change).  Since the planner sees only one row coming out of the low level
join, it uses nested loops all the way up chain when it would be more
efficient to use another join type.  In our informal testing, we found that
by disabling nested loops and forcing other join types, we could get
fantastic speedups.  Those queries that seem to benefit most from this have
a lot of sub-queries being built up into a final query set as well as a fair
number of joins in the sub-queries.  Since these are user created and are
then generated via our tools, they can be quite messy at times.
After doing this testing, have since added some functionality in our ad hoc
reporting tool to allow us to tune individual queries by turning on and off
individual join types at runtime.  As we hear of slow reports, we've been
individually turning off the nested loops on those reports.  Almost always,
this has increased the performance of the reports, sometimes in a completely
amazing fashion (many, many minutes to seconds at times).  It of course
doesn't help everything and turning off nested loops in general causes
overall slowdown in other parts of the system.

As this has gone on over the last couple of weeks, it feels like we either
have a misconfiguration on the server, or we are tickling a mis-estimation
bug in the planner.  I'm hoping it's the former.  The db server has 8G of
memory and raid1 -wal, raid10- data configuration, os is linux 2.6.9, db is
8.2.6.  The db is a utf-8 db if that is of any bearing and autovac and
bgwriter are on.

Nondefault settings of interest from postgresql.conf


shared_buffers = 1024MB # min 128kB or max_connections*16kB
work_mem = 256MB# min 64kB
maintenance_work_mem = 256MB# min 1MB
random_page_cost = 1.75 # same scale as above
effective_cache_size = 4096MB
default_statistics_target = 100 # range 1-1000


If nothing else, perhaps this will help somebody else who has run into the
same problem.  If explain analyze of a query shows a large mis-estimation of
rows returned on a join (estimate=1, actual=2k) causing the planner to
choose nested loops instead of another join type, you might try running the
query with nested loops set to off and see if that helps w/ performance.

Thanks,

-Chris


Re: [PERFORM] Planner mis-estimation using nested loops followup

2008-03-18 Thread Chris Kratz
Y, turning nested loops off in specific cases has increased performance
greatly.  It didn't fix the planner mis-estimation, just the plan it chose.
 It's certainly not a panacea, but it's something we now try early on when
trying to speed up a query that matches these characteristics.
-Chris

On 3/18/08, Joshua D. Drake [EMAIL PROTECTED] wrote:

 -BEGIN PGP SIGNED MESSAGE-
 Hash: SHA1


 On Tue, 18 Mar 2008 11:35:08 -0400
 Chris Kratz [EMAIL PROTECTED] wrote:

  Nondefault settings of interest from postgresql.conf
 
 
  shared_buffers = 1024MB # min 128kB or
  max_connections*16kB work_mem = 256MB
  # min 64kB maintenance_work_mem = 256MB# min 1MB
  random_page_cost = 1.75 # same scale as above
  effective_cache_size = 4096MB
  default_statistics_target = 100 # range 1-1000
 
 
  If nothing else, perhaps this will help somebody else who has run
  into the same problem.  If explain analyze of a query shows a large
  mis-estimation of rows returned on a join (estimate=1, actual=2k)
  causing the planner to choose nested loops instead of another join
  type, you might try running the query with nested loops set to off
  and see if that helps w/ performance.


 Did you try that? Did it work?

 Joshua D. Drake


 - --
 The PostgreSQL Company since 1997: http://www.commandprompt.com/
 PostgreSQL Community Conference: http://www.postgresqlconference.org/
 Donate to the PostgreSQL Project: http://www.postgresql.org/about/donate
   PostgreSQL political pundit | Mocker of Dolphins

 -BEGIN PGP SIGNATURE-
 Version: GnuPG v1.4.6 (GNU/Linux)

 iD8DBQFH3+TlATb/zqfZUUQRAmXUAKCjwidfW0KXjzUM26I4yTx94/wSiQCfaqWU
 eI9i5yucBH718okW3w2UewQ=
 =BO3E
 -END PGP SIGNATURE-



[PERFORM] Ramifications of turning off Nested Loops for slow queries

2008-03-04 Thread Chris Kratz

Hello Everyone,

I had posted an issue previously that we've been unable to resolve.   
An early mis-estimation in one or more subqueries causes the remainder  
of the query to choose nested loops instead of a more efficient method  
and runs very slowly (CPU Bound).  I don't think there is any way to  
suggest to the planner it not do what it's doing, so we are starting  
to think about turning off nested loops entirely.


Here is the history so far:

http://archives.postgresql.org/pgsql-performance/2008-02/msg00205.php

At the suggestion of the list, we upgraded to 8.2.6 and are still  
experiencing the same problem.  I'm now installing 8.3 on my  
workstation  to see if it chooses a better plan, but it will take some  
time to get it compiled, a db loaded, etc.


We have a number of very long running reports that will run in seconds  
if nested loops are turned off.  The other alternative we are  
exploring is programmatically turning off nested loops just for the  
problematic reports.  But with the speedups we are seeing, others are  
getting gun shy about having them on at all.


So, I've now been asked to ping the list as to whether turning off  
nested loops system wide is a bad idea, and why or why not.


Any other thoughts or suggestions?

Thanks,

-Chris

--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your Subscription:
http://mail.postgresql.org/mj/mj_wwwusr?domain=postgresql.orgextra=pgsql-performance


Re: [PERFORM] Ramifications of turning off Nested Loops for slow queries

2008-03-04 Thread Chris Kratz
On 3/4/08, Kevin Grittner [EMAIL PROTECTED] wrote:

  On Tue, Mar 4, 2008 at  8:42 AM, in message
  Any other thoughts or suggestions?


 Make sure your effective_cache_size is properly configured.

 Increase random_page_cost and/or decrease seq_page_cost.
 You can play with the cost settings on a connection, using EXPLAIN
 on the query, to see what plan you get with each configuration
 before putting it into the postgresql.conf file.


 -Kevin


That was a good idea.  I hadn't tried playing with those settings in a
session.  This is a 8G box, and we've dedicated half of that (4G) to the
file system cache.  So, 4G is what effective_cache_size is set to.  Our
seq_page_cost is set to 1 and our random_page_cost is set to 1.75 in the
postgresql.conf.

In testing this one particular slow query in a session, I changed these
settings alternating in increments of 0.25.  The random_page_cost up to 4
and the seq_page_cost down to 0.25.  This made perhaps a second difference,
but at the end, we were back to to the 37s.  Doing a set enable_nestloop=off
in the session reduced the runtime to 1.2s with the other settings back to
our normal day to day settings.

So, for now I think we are going to have to modify the code to prepend the
problematic queries with this setting and hope the estimator is able to
better estimate this particular query in 8.3.

Thanks for the suggestions,

-Chris


Re: [PERFORM] Ramifications of turning off Nested Loops for slow queries

2008-03-04 Thread Chris Kratz
On 3/4/08, Tom Lane [EMAIL PROTECTED] wrote:

 Kevin Grittner [EMAIL PROTECTED] writes:
  On Tue, Mar 4, 2008 at  8:42 AM, in message
  [EMAIL PROTECTED], Chris Kratz
  [EMAIL PROTECTED] wrote:
  So, I've now been asked to ping the list as to whether turning off
  nested loops system wide is a bad idea, and why or why not.

  In our environment, the fastest plan for a lot of queries involve
  nested loops.  Of course, it's possible that these never provide the
  fasted plan in your environment, but it seems very unlikely --
  you're just not noticing the queries where it's doing fine.


 Yeah, I seem to recall similar queries from other people who were
 considering the opposite, ie disabling the other join types :-(

 The rule of thumb is that nestloop with an inner indexscan will beat
 anything else for pulling a few rows out of a large table.  But on
 the other hand it loses big for selecting lots of rows.  I don't think
 that a global disable in either direction would be a smart move, unless
 you run only a very small number of query types and have checked them
 all.

 regards, tom lane


So, if we can't find another way to solve the problem, probably our best bet
is to turn off nested loops on particularly bad queries by prepending them
w/ set enable_nested_loop=off?  But, leave them on for the remainder of the
system?

Do you think it's worth testing on 8.3 to see if the estimator is able to
make a better estimate?

-Chris


Re: [PERFORM] mis-estimate in nested query causes slow runtimes

2008-02-18 Thread Chris Kratz
On 2/11/08, Tom Lane [EMAIL PROTECTED] wrote:

 Chris Kratz [EMAIL PROTECTED] writes:
  The first frustration is that I can't get the transaction details scan
  to get any more accurate.  It thinks it will find 1407 records,
  instead it finds 20,153.  Then for whatever reason it thinks that a
  join between 1 record and 1407 records will return 1 record.  This is
  mainly what I can't understand.  Why does it think it will only get
  one record in response when it's a left join?

 I don't see any left join there ...

  PG 8.2.4 on Linux kernel 2.6.9 x64

 The first thing you should do is update to 8.2.6; we've fixed a fair
 number of problems since then that were fallout from the outer-join
 planning rewrite in 8.2.

 If it still doesn't work very well, please post the pg_stats rows for
 the join columns involved (idatrndtl.ida_trans_match_source_id and
 mtchsrcprj3.id).  (You do have up-to-date ANALYZE stats for both
 of those tables, right?)

 regards, tom lane


Hello Tom,

We've updated to Postgres 8.2.6 on our production database over the weekend.
 Unfortunately, the estimates on this query are no better after the upgrade.
 Here is just the part of the estimate that is incorrect.  (2 vs 20153)

-  Nested Loop  (cost=12.68..165.69 rows=2 width=38) (actual time=
0.089..29.792 rows=20153 loops=1)
  -  Hash Join  (cost=12.68..24.37 rows=1 width=24) (actual time=
0.064..0.135 rows=1 loops=1)
Hash Cond: (mtchsrcprj3.funding_source_id = mtchsrcprjfs3.nameid
)
-  Seq Scan on project mtchsrcprj3  (cost=0.00..11.22 rows=122
width=8) (actual time=0.002..0.053 rows=122 loops=1)
-  Hash  (cost=12.61..12.61 rows=6 width=24) (actual time=
0.017..0.017 rows=1 loops=1)
  -  Index Scan using name_float_lfm_idx on namemaster
mtchsrcprjfs3  (cost=0.00..12.61 rows=6 width=24) (actual
time=0.012..0.013rows=1 loops=1)
Index Cond: (name_float_lfm = 'DWS'::text)
  -  Index Scan using transaction_details_ida_trans_match_source_id on
transaction_details idatrndtl  (cost=0.00..123.72 rows=1408 width=22)
(actual time=0.023..17.128 rows=20153 loops=1)

(Entire explain analyze posted earlier in thread)

Total Query runtime: 35309.298 ms
Same w/ enable_nestloop off: 761.715 ms

I've tried the stats up to 1000 on both columns which causes no differences.
 Currently the stats are at 100.

test=# alter table transaction_details alter column
ida_trans_match_source_id set statistics 100;
ALTER TABLE
test=# analyze transaction_details;
ANALYZE
test=# alter table project alter column id set statistics 100;
ALTER TABLE
test=# analyze project;
ANALYZE

Stats rows in pg_stats for these two columns:

test=# select * from pg_stats where tablename = 'transaction_details' and
attname='ida_trans_match_source_id';
 schemaname |  tablename  |  attname  | null_frac |
avg_width | n_distinct |   most_common_vals
  | most_common_freqs
  |

 histogram_bounds
  | correlation
+-+---+---+---++--+---+-+-
 public | transaction_details | ida_trans_match_source_id |  0.479533 |
4 | 69 |
{818,832,930,937,923,812,931,836,837,829,830,14,809} | {0.1024,0.0991333,
0.0408,0.0232,0.0221,0.0219,0.0207,0.0188667,0.0186667,0.0177667,0.0176667,
0.0130333,0.0118667} |
{6,802,813,813,814,814,815,815,816,816,817,817,827,827,833,835,835,838,838,838,838,838,843,920,921,921,921,921,922,922,924,924,924,924,925,926,926,928,928,934,936,936,936,936,936,938,939,941,941,955,965,967,968,968,974,980}
|0.178655
(1 row)

test=# select * from pg_stats where tablename = 'project' and attname='id';
 schemaname | tablename | attname | null_frac | avg_width | n_distinct |
most_common_vals | most_common_freqs |


 histogram_bounds

   | correlation
+---+-+---+---++--+---++-
 public | project   | id

Re: [PERFORM] mis-estimate in nested query causes slow runtimes

2008-02-12 Thread Chris Kratz
On 2/11/08, Tom Lane [EMAIL PROTECTED] wrote:

 Chris Kratz [EMAIL PROTECTED] writes:
-  Nested Loop  (cost=42.74..161.76 rows=1 width=38) (actual
  time=2.932..27.772 rows=20153 loops=1)
  -  Hash Join  (cost=10.89..22.58 rows=1 width=24) (actual
  time=0.065..0.134 rows=1 loops=1)
Hash Cond: (mtchsrcprj3.funding_source_id =
  mtchsrcprjfs3.nameid)
-  Seq Scan on project mtchsrcprj3  (cost=0.00..11.22
  rows=122 width=8) (actual time=0.002..0.054 rows=122 loops=1)
-  Hash  (cost=10.83..10.83 rows=5 width=24) (actual
  time=0.017..0.017 rows=1 loops=1)
  -  Index Scan using name_float_lfm_idx on
  namemaster mtchsrcprjfs3  (cost=0.00..10.83 rows=5 width=24) (actual
  time=0.012..0.013 rows=1 loops=1)
Index Cond: (name_float_lfm = 'DWS'::text)
  -  Bitmap Heap Scan on transaction_details idatrndtl
  (cost=31.85..121.60 rows=1407 width=22) (actual time=2.864..12.060
  rows=20153 loops=1)
Recheck Cond: (idatrndtl.ida_trans_match_source_id =
  mtchsrcprj3.id)
-  Bitmap Index Scan on
  transaction_details_ida_trans_match_source_id  (cost=0.00..31.50
  rows=1407 width=0) (actual time=2.696..2.696 rows=20153 loops=1)
  Index Cond: (idatrndtl.ida_trans_match_source_id =
  mtchsrcprj3.id)

  The first frustration is that I can't get the transaction details scan
  to get any more accurate.  It thinks it will find 1407 records,
  instead it finds 20,153.  Then for whatever reason it thinks that a
  join between 1 record and 1407 records will return 1 record.  This is
  mainly what I can't understand.  Why does it think it will only get
  one record in response when it's a left join?

 I don't see any left join there ...

  PG 8.2.4 on Linux kernel 2.6.9 x64

 The first thing you should do is update to 8.2.6; we've fixed a fair
 number of problems since then that were fallout from the outer-join
 planning rewrite in 8.2.

 If it still doesn't work very well, please post the pg_stats rows for
 the join columns involved (idatrndtl.ida_trans_match_source_id and
 mtchsrcprj3.id).  (You do have up-to-date ANALYZE stats for both
 of those tables, right?)

 regards, tom lane



I know it's somewhat premature as we haven't had a chance to do the update
yet, but here is what I did w/ the statistics with the current version for
chuckles and grins just to see if it would make a difference in the plan.

# alter table project alter column id set statistics 1000;
ALTER TABLE
# analyze project;
ANALYZE
# alter table transaction_details alter column ida_trans_match_source_id set
statistics 1000;
ALTER TABLE
# analyze transaction_details;
ANALYZE
# select * from pg_stats where (tablename='project' and attname='id') or
(tablename='transaction_details' and attname='ida_trans_match_source_id');
 schemaname |  tablename  |  attname  | null_frac |
avg_width | n_distinct |
  most_common_vals
|

most_common_freqs


 |


   histogram_bounds


 | correlation
+-+---+---+---++--+++-
 public | project | id| 0 |
4 | -1 |

 |




 |
{6,7,8,12,13,14,15,17,18,19,24,25,26,27,28,29,30,31,32,33,34,35,36,37,41,42,71,72,797,802,803,809,812,813,814,815,816,817,818,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,920,921,922,923,92

Re: [PERFORM] mis-estimate in nested query causes slow runtimes

2008-02-12 Thread Chris Kratz
On 2/11/08, Tom Lane [EMAIL PROTECTED] wrote:

 Chris Kratz [EMAIL PROTECTED] writes:
-  Nested Loop  (cost=42.74..161.76 rows=1 width=38) (actual
  time=2.932..27.772 rows=20153 loops=1)
  -  Hash Join  (cost=10.89..22.58 rows=1 width=24) (actual
  time=0.065..0.134 rows=1 loops=1)
Hash Cond: (mtchsrcprj3.funding_source_id =
  mtchsrcprjfs3.nameid)
-  Seq Scan on project mtchsrcprj3  (cost=0.00..11.22
  rows=122 width=8) (actual time=0.002..0.054 rows=122 loops=1)
-  Hash  (cost=10.83..10.83 rows=5 width=24) (actual
  time=0.017..0.017 rows=1 loops=1)
  -  Index Scan using name_float_lfm_idx on
  namemaster mtchsrcprjfs3  (cost=0.00..10.83 rows=5 width=24) (actual
  time=0.012..0.013 rows=1 loops=1)
Index Cond: (name_float_lfm = 'DWS'::text)
  -  Bitmap Heap Scan on transaction_details idatrndtl
  (cost=31.85..121.60 rows=1407 width=22) (actual time=2.864..12.060
  rows=20153 loops=1)
Recheck Cond: (idatrndtl.ida_trans_match_source_id =
  mtchsrcprj3.id)
-  Bitmap Index Scan on
  transaction_details_ida_trans_match_source_id  (cost=0.00..31.50
  rows=1407 width=0) (actual time=2.696..2.696 rows=20153 loops=1)
  Index Cond: (idatrndtl.ida_trans_match_source_id =
  mtchsrcprj3.id)

  The first frustration is that I can't get the transaction details scan
  to get any more accurate.  It thinks it will find 1407 records,
  instead it finds 20,153.  Then for whatever reason it thinks that a
  join between 1 record and 1407 records will return 1 record.  This is
  mainly what I can't understand.  Why does it think it will only get
  one record in response when it's a left join?

 I don't see any left join there ...

  PG 8.2.4 on Linux kernel 2.6.9 x64

 The first thing you should do is update to 8.2.6; we've fixed a fair
 number of problems since then that were fallout from the outer-join
 planning rewrite in 8.2.

 If it still doesn't work very well, please post the pg_stats rows for
 the join columns involved (idatrndtl.ida_trans_match_source_id and
 mtchsrcprj3.id).  (You do have up-to-date ANALYZE stats for both
 of those tables, right?)

 regards, tom lane


Thanks Tom, we will try the upgrade and see if that makes a difference.


-Chris


[PERFORM] mis-estimate in nested query causes slow runtimes

2008-02-11 Thread Chris Kratz

Hello,

I've been wrestling w/ a complex query for another developer for  
awhile today.  The problem consistently seems to a mis-estimation of  
the number of rows resulting from a join.  This causes the query early  
on to think it's only going to be processing 1 row and so it chooses  
nested loops much of the way up the chain.  I've messed w/ statistics  
targets on some of the columns w/ no increase in the accuracy of the  
estimates.  I've analyzed the tables in question (autovac is  
running).  If I turn off nested loops, the query runs in 1.5 seconds.   
Otherwise it takes about 37s.  With other criteria in the where clause  
it can take many minutes to return.  Here is a subset of the explain  
analyze that I'm wrestling with.  The entire explain is at the end of  
the email.


 -  Nested Loop  (cost=42.74..161.76 rows=1 width=38) (actual  
time=2.932..27.772 rows=20153 loops=1)
   -  Hash Join  (cost=10.89..22.58 rows=1 width=24) (actual  
time=0.065..0.134 rows=1 loops=1)
 Hash Cond: (mtchsrcprj3.funding_source_id =  
mtchsrcprjfs3.nameid)
 -  Seq Scan on project mtchsrcprj3  (cost=0.00..11.22  
rows=122 width=8) (actual time=0.002..0.054 rows=122 loops=1)
 -  Hash  (cost=10.83..10.83 rows=5 width=24) (actual  
time=0.017..0.017 rows=1 loops=1)
   -  Index Scan using name_float_lfm_idx on  
namemaster mtchsrcprjfs3  (cost=0.00..10.83 rows=5 width=24) (actual  
time=0.012..0.013 rows=1 loops=1)

 Index Cond: (name_float_lfm = 'DWS'::text)
   -  Bitmap Heap Scan on transaction_details idatrndtl   
(cost=31.85..121.60 rows=1407 width=22) (actual time=2.864..12.060  
rows=20153 loops=1)
 Recheck Cond: (idatrndtl.ida_trans_match_source_id =  
mtchsrcprj3.id)
 -  Bitmap Index Scan on  
transaction_details_ida_trans_match_source_id  (cost=0.00..31.50  
rows=1407 width=0) (actual time=2.696..2.696 rows=20153 loops=1)
   Index Cond: (idatrndtl.ida_trans_match_source_id =  
mtchsrcprj3.id)


The first frustration is that I can't get the transaction details scan  
to get any more accurate.  It thinks it will find 1407 records,  
instead it finds 20,153.  Then for whatever reason it thinks that a  
join between 1 record and 1407 records will return 1 record.  This is  
mainly what I can't understand.  Why does it think it will only get  
one record in response when it's a left join?


The thing is that we've had this happen a number of times recently  
with complex nested queries.  Most of the time things will run very  
quickly, but an early mis-estimation by the planner causes it to use  
nested loops exclusively when hash joins would be more appropriate.


Is there anything I can do to improve this short of the set  
enable_nestloop=off?


PG 8.2.4 on Linux kernel 2.6.9 x64

-Chris

---  Full explain analyze -

Group  (cost=336.76..336.82 rows=1 width=328) (actual  
time=36620.831..36621.176 rows=248 loops=1)
   -  Sort  (cost=336.76..336.76 rows=1 width=328) (actual  
time=36620.828..36620.888 rows=248 loops=1)
 Sort Key: county, fullname_last_first_mdl, CASE WHEN  
(COALESCE(fullname_last_first_mdl, '0'::text) = '0'::text) THEN  
''::text ELSE COALESCE(fullname_last_first_mdl, '0'::text) END || '  
'::text) || '-'::text) || ' '::text) || CASE WHEN (COALESCE(ssn,  
'0'::text) = '0'::text) THEN ''::text ELSE COALESCE(ssn, '0'::text)  
END), system_name_id, ssn, ida_account_id,  
ida_account_match_source_funding_source_name_float_lfm,  
ida_account_status, vs_query_27453_212267, vs_query_27453_212252,  
vs_query_27453_212253, vs_query_27453_212254, vs_query_27453_212255,  
(COALESCE(vs_query_27453_212267, 0::numeric) +  
COALESCE(vs_query_27453_212255, 0::numeric))
 -  Subquery Scan foo  (cost=336.72..336.75 rows=1  
width=328) (actual time=36614.750..36615.319 rows=248 loops=1)
   -  Sort  (cost=336.72..336.72 rows=1 width=255)  
(actual time=36614.737..36614.798 rows=248 loops=1)

 Sort Key: cou.validvalue, dem.name_float_lfm
 -  Nested Loop Left Join  (cost=194.80..336.71  
rows=1 width=255) (actual time=506.599..36611.702 rows=248 loops=1)
   -  Nested Loop Left Join   
(cost=194.80..332.90 rows=1 width=242) (actual time=506.566..36606.528  
rows=248 loops=1)
 Join Filter: (acc.id =  
qry27453.ida_account_id)
 -  Nested Loop  (cost=30.16..168.13  
rows=1 width=82) (actual time=0.461..27.079 rows=248 loops=1)
   -  Nested Loop   
(cost=30.16..167.85 rows=1 width=90) (actual time=0.453..25.133  
rows=248 loops=1)
 -  Nested Loop   
(cost=30.16..165.94 rows=1 width=77) (actual time=0.441..19.687  
rows=970 loops=1)
   -  Nested Loop   
(cost=30.16..162.90 rows=1 width=40) (actual 

Re: [PERFORM] Incorrect estimates on columns

2007-10-18 Thread Chris Kratz
On Wednesday 17 October 2007 20:23, Tom Lane wrote:
  Chris Kratz [EMAIL PROTECTED] writes:
  On Wednesday 17 October 2007 14:49, Tom Lane wrote:
  Evidently it's not realizing that every row of par will have a join
  partner, but why not?  I suppose a.activityid is unique, and in most
  cases that I've seen the code seems to get that case right.
 
  Would you show us the pg_stats rows for par.activity and a.activityid?
 
  Here are the pg_stats rows for par.activity and a.activityid.

 Hmm, nothing out of the ordinary there.

 I poked at this a bit and realized that what seems to be happening is
 that the a.programid = 171 condition is reducing the selectivity
 estimate --- that is, it knows that that will filter out X percent of
 the activity rows, and it assumes that *the size of the join result will
 be reduced by that same percentage*, since join partners would then be
 missing for some of the par rows.  The fact that the join result doesn't
 actually decrease in size at all suggests that there's some hidden
 correlation between the programid condition and the condition on
 par.provider_lfm.  Is that true?  Maybe you could eliminate one of the
 two conditions from the query?

 Since PG doesn't have any cross-table (or even cross-column) statistics
 it's not currently possible for the optimizer to deal very well with
 hidden correlations like this ...

   regards, tom lane

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

Yes, you are correct.  Programid is a guard condition to make sure a user 
cannot look at rows outside of their program.  In this particular case the 
par table only has rows for this agency (at one point in time, all rows were 
in one table), so I was able to remove  the check on programid on a. This 
causes my example query to run in 200ms.   That's wonderful.

So, to recap.  We had a filter on the join clause which really didn't in this 
case affect the selectivity of the join table.  But the optimizer assumed 
that the selectivity would be affected causing it to think the join would 
generate only a few rows.  Since it thought that there would be relatively 
few rows returned, it used a nestloop instead of another type of join that 
would have been faster with larger data sets.

Thanks for all your help.

-Chris 

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

   http://archives.postgresql.org


[PERFORM] Incorrect estimates on columns

2007-10-17 Thread Chris Kratz
Hello Everyone,

I'm struggling to get postgres to run a particular query quickly.  It seems 
that very early on, the planner seems to mis-estimate the number of rows 
returned by a join which causes it to assume that there is only 1 row as it 
goes up the tree.  It then picks a nested loop join which seems to cause the 
whole query to be slow.   Or at least if I turn off nestloop, it runs in 216ms.

explain analyze SELECT 1
FROM 
   rpt_agencyquestioncache_171_0 par 
   right outer join namemaster dem on (par.nameid = dem.nameid and 
dem.programid  = 171) 
   right join activity_parentid_view ses on (par.activity = ses.activityid and 
ses.programid=171) 
   left join   (
  select ct0.inter_agency_id,ct0.nameid 
  from rpt_agencyquestioncache_171_0 ct0 
  join rpt_agencyquestioncache_171_2 ct2 on ct2.participantid 
=ct0.participantid
  ) as   par30232   on (dem.nameid=par30232.nameid and 
par30232.inter_agency_id=30232)
WHERE 
   ( ( (par.provider_lfm) ='Child Guidance Treatment Centers Inc.'))

  QUERY 
PLAN
--
 Nested Loop Left Join  (cost=1990.12..5666.92 rows=1 width=0) (actual 
time=82.185..91511.455 rows=1199 loops=1)
   Join Filter: (dem.nameid = ct0.nameid)
   -  Nested Loop Left Join  (cost=45.92..1324.06 rows=1 width=4) (actual 
time=0.973..74.206 rows=1199 loops=1)
 -  Nested Loop  (cost=45.92..1323.33 rows=1 width=8) (actual 
time=0.964..61.264 rows=1199 loops=1)
   -  Hash Join  (cost=45.92..1251.07 rows=21 width=8) (actual 
time=0.948..10.439 rows=1199 loops=1)
 Hash Cond: (par.activity = a.activityid)
 -  Bitmap Heap Scan on rpt_agencyquestioncache_171_0 par  
(cost=21.92..1222.19 rows=1247 width=8) (actual time=0.415..3.081 rows=1199 
loops=1)
   Recheck Cond: (provider_lfm = 'Child Guidance 
Treatment Centers Inc.'::text)
   -  Bitmap Index Scan on rpt_aqc_45604_provider_lfm  
(cost=0.00..21.61 rows=1247 width=0) (actual time=0.394..0.394 rows=1199 
loops=1)
 Index Cond: (provider_lfm = 'Child Guidance 
Treatment Centers Inc.'::text)
 -  Hash  (cost=19.21..19.21 rows=383 width=4) (actual 
time=0.513..0.513 rows=383 loops=1)
   -  Index Scan using activity_programid_idx on 
activity a  (cost=0.00..19.21 rows=383 width=4) (actual time=0.034..0.307 
rows=383 loops=1)
 Index Cond: (programid = 171)
   -  Index Scan using nameid_pk on namemaster dem  
(cost=0.00..3.43 rows=1 width=4) (actual time=0.023..0.036 rows=1 loops=1199)
 Index Cond: (par.nameid = dem.nameid)
 Filter: (programid = 171)
 -  Index Scan using activity_session_session_idx on activity_session 
s  (cost=0.00..0.72 rows=1 width=4) (actual time=0.007..0.007 rows=0 loops=1199)
   Index Cond: (a.activityid = s.session)
   -  Hash Join  (cost=1944.20..4292.49 rows=4029 width=4) (actual 
time=59.732..74.897 rows=4130 loops=1199)
 Hash Cond: (ct2.participantid = ct0.participantid)
 -  Seq Scan on rpt_agencyquestioncache_171_2 ct2  (cost=0.00..1747.00 
rows=74800 width=4) (actual time=0.008..28.442 rows=74800 loops=1199)
 -  Hash  (cost=1893.84..1893.84 rows=4029 width=8) (actual 
time=5.578..5.578 rows=4130 loops=1)
   -  Bitmap Heap Scan on rpt_agencyquestioncache_171_0 ct0  
(cost=55.48..1893.84 rows=4029 width=8) (actual time=0.625..3.714 rows=4130 
loops=1)
 Recheck Cond: (inter_agency_id = 30232)
 -  Bitmap Index Scan on rpt_aqc_45604_inter_agency_id  
(cost=0.00..54.47 rows=4029 width=0) (actual time=0.609..0.609 rows=4130 
loops=1)
   Index Cond: (inter_agency_id = 30232)
 Total runtime: 91514.109 ms
(27 rows)

I've increased statistics to 100 of all pertinent columns in the query to no 
effect.

I've vacuumed and all analyzed all tables in question.  Autovac is on.

Settings of interest in postgresql.conf:

shared_buffers = 1024MB 
work_mem = 256MB
maintenance_work_mem = 256MB 
random_page_cost = 2.0

PG version: 8.2.4
Server Mem: 2G Ram

If I reduce random_page_cost to 1.0, I get the following query plan.

  QUERY PLAN
---
 Nested Loop Left Join  (cost=20.87..4377.13 rows=1 width=0) (actual 
time=146.402..29585.011 rows=1199 loops=1)
   -  Nested Loop Left Join  (cost=20.87..4376.62 rows=1 width=4) (actual 

Re: [PERFORM] Incorrect estimates on columns

2007-10-17 Thread Chris Kratz
On Wednesday 17 October 2007 14:49, Tom Lane wrote:
  Chris Kratz [EMAIL PROTECTED] writes:
  I'm struggling to get postgres to run a particular query quickly.

 The key problem seems to be the join size misestimate here:
 -  Hash Join  (cost=45.92..1251.07 rows=21 width=8)
  (actual time=0.948..10.439 rows=1199 loops=1) Hash Cond: (par.activity =
  a.activityid)
   -  Bitmap Heap Scan on
  rpt_agencyquestioncache_171_0 par  (cost=21.92..1222.19 rows=1247
  width=8) (actual time=0.415..3.081 rows=1199 loops=1) -  Hash 
  (cost=19.21..19.21 rows=383 width=4) (actual time=0.513..0.513 rows=383
  loops=1)

 Evidently it's not realizing that every row of par will have a join
 partner, but why not?  I suppose a.activityid is unique, and in most
 cases that I've seen the code seems to get that case right.

 Would you show us the pg_stats rows for par.activity and a.activityid?

   regards, tom lane

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

http://archives.postgresql.org


Thanks for the reply and help Tom, 

activityid is unique on the activity table.
activity on par is a child table to activity, with multiple rows per activityid.

Here are the pg_stats rows for par.activity and a.activityid.

# select * from pg_stats where tablename='activity' and attname='activityid';
 schemaname | tablename |  attname   | null_frac | avg_width | n_distinct | 
most_common_vals | most_common_freqs |  



  histogram_bounds  


   
| correlation
+---++---+---++--+---+-+-
 public | activity  | activityid | 0 | 4 | -1 | 
 |   | 
{232,2497,3137,3854,4210,5282,9318,11396,12265,12495,12760,13509,13753,15000,15379,15661,16791,17230,17703,18427,18987,19449,19846,20322,20574,20926,21210,21501,21733,22276,22519,23262,24197,24512,24898,25616,25893,26175,26700,27141,27509,27759,29554,29819,30160,30699,32343,32975,33227,33493,33753,33980,34208,34534,34780,35007,35235,35641,35922,36315,36678,37998,38343,38667,39046,39316,39778,40314,40587,40884,41187,41860,42124,42399,42892,43313,43546,43802,45408,45740,46030,46406,46655,47031,47556,47881,48190,48528,48810,49038,49319,49704,49978,50543,50916,51857,52134,52380,52691,53011,53356}
 |0.703852
(1 row)

# select * from pg_stats where tablename='rpt_agencyquestioncache_171_0' and 
attname='activity';
 schemaname |   tablename   | attname  | null_frac | avg_width 
| n_distinct | most_common_vals 
 |  
 most_common_freqs  
 |  



  histogram_bounds  


   | 
correlation

Re: [PERFORM] Help with performance on current status column

2005-09-14 Thread Chris Kratz
Hello Richard,

Thank you for the response.  I did forget to mention that the columns have the 
following meanings.

One, if a begin or end date is null, it means that the role is open ended in 
that direction.  For example, if there is no end date, that means currently 
the role will go on forever beginning with the start date.  Your idea of 
using minimal and maximum dates is an interesting one and not one that I had 
considered.  I will do some testing later today and see if that makes a 
difference.

The other option I am toying with is simply having a status column which is 
updated nightly via a cron job.  This will probably be the most efficient and 
can be indexed.

I also forgot to say that we have seen this behavior on 2 boxes both on Linux 
(Red Hat ES  Mandrake) and both are running Postgres 8.0 (8.0.1 and 8.0.3).  
Strangely, after playing with statistics some yesterday (setting from 10 to 
100 to 1000 and back to 10 and analyzing), the 8.0.1 machine picks a 
different plan and runs in a 101.104ms.  The larger machine (dual proc Opt, 6 
disk raid 10, etc) with 8.0.3 still takes 3-5minutes to run the same query 
with the same data set even after playing with statistics and repeated 
analyze on the same table.  It just seems odd.  It seems it is picking the 
incorrect plan based off of an overly optimistic estimate of rows returned 
from the calculation.

The other frustration with this is that this sql is machine generated which is 
why we have some of the awkwardness in the calculation.  That calc gets used 
for a lot of different things including column definitions when people want 
to see the column on screen.

Thanks,

-Chris

On Wednesday 14 September 2005 05:13 am, Richard Huxton wrote:
 Chris Kratz wrote:
  Hello All,
 
  We are struggling with a specific query that is killing us.  When doing
  explain analyze on the entire query, we *seem* to be getting killed by
  the estimated number of rows on a case statement calculation.
 
  I've included a snippet from the explain analyze of the much larger
  query. The line in question, (cost=0.00..106.52 rows=1 width=16) (actual
  time=0.048..67.728 rows=4725 loops=1) shows that it returned 4700 rows
  instead of 1 which when coupled with a later join causes the statement to
  run over 3 minutes.[1]
 
  It seems that it thinks that the scan on role_id is going to return 1
  row, but in reality returns 4725 rows.  The case statement causing the
  problem uses todays date to see if a particular row is still active. 
  Here is a test case showing how far off the estimate is from the reality.
  [2]
 
  [2] A much simpler statement triggers the incorrect row counts here.
 
  explain analyze
  select *
  from roles rol
  where
 
  CASE
 WHEN rol.role_id IS NULL
 THEN NULL
 WHEN rol.begin IS NOT NULL and rol.end IS NOT NULL
 THEN
   CASE WHEN TIMESTAMP 'now'=rol.begin and TIMESTAMP
  'now'=rol.end
   THEN 'Active'
   ELSE 'Inactive' END
 WHEN rol.begin IS NOT NULL
 THEN
   CASE WHEN TIMESTAMP 'now'=rol.begin
   THEN 'Active'
   ELSE 'Inactive' END
 WHEN rol.end IS NOT NULL
 THEN
   CASE WHEN TIMESTAMP 'now'=rol.end
   THEN 'Active'
   ELSE 'Inactive' END
 ELSE 'Active'
 END = 'Active'

 Aside #1 - I'm not entirely clear how role_id can be null since you
 seemed to be joining against it in the real query.

 Aside #2 - You're probably better off with CURRENT_DATE since begin/end
 seem to be dates, rather than TIMESTAMP 'now' - and in any case you
 wanted timestamp with time zone

 OK, I think the root of your problem is your use of null to mean not
 ended or not started (whatever 'not started' means). PostgreSQL has
 the handy timestamptz value infinity, but only for timestamps and not
 for dates. I'd probably cheat a little and use an end date of
 '-12-31' or similar to simulate infinity. Then your test is simply:

 WHERE
...
AND (rol.begin = CURRENT_DATE AND rol.end = CURRENT_DATE)

 That should estimate simply enough.

 --
Richard Huxton
Archonet Ltd

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

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

-- 
Chris Kratz

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

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


[PERFORM] Help with performance on current status column

2005-09-13 Thread Chris Kratz
Hello All,

We are struggling with a specific query that is killing us.  When doing 
explain analyze on the entire query, we *seem* to be getting killed by the 
estimated number of rows on a case statement calculation.

I've included a snippet from the explain analyze of the much larger query. The 
line in question, (cost=0.00..106.52 rows=1 width=16) (actual 
time=0.048..67.728 rows=4725 loops=1) shows that it returned 4700 rows 
instead of 1 which when coupled with a later join causes the statement to run 
over 3 minutes.[1] 

It seems that it thinks that the scan on role_id is going to return 1 row, but 
in reality returns 4725 rows.  The case statement causing the problem uses 
todays date to see if a particular row is still active.  Here is a test case 
showing how far off the estimate is from the reality. [2]

I'm not too surprised to see that the estimate is off because it is 
calculated, but does anyone know either how to make the estimate more 
accurate so it picks a better plan, or is there a better way to do a status 
function based off of the current date so that it is more efficient?  I've 
played with statistics on this table (racheting them up to 1000) with no 
change in the plan.

Any thoughts?

-Chris

[1] explain analyze snippet from larger query
-  Nested Loop  (cost=0.00..955.70 rows=1 width=204) (actual 
time=3096.689..202704.649 rows=17 loops=1)
  Join Filter: (inner.nameid = outer.name_id)
  -  Nested Loop  (cost=0.00..112.25 rows=1 width=33) (actual 
time=0.271..90.760 rows=4725 loops=1)
-  Index Scan using role_definition_description_idx on 
role_definition rdf  (cost=0.00..5.72 rows=1 width=21) (actual 
time=0.215..0.218 rows=1 loops=1)
  Index Cond: (description = 'Participant'::text)
  Filter: (program_id = 120)
-  Index Scan using roles_role_id_idx on roles rol  
(cost=0.00..106.52 rows=1 width=16) (actual time=0.048..67.728 rows=4725 
loops=1)
  Index Cond: (rol.role_id = outer.role_id)
  Filter: (CASE WHEN (role_id IS NULL) THEN NULL::text WHEN 
((begin IS NOT NULL) AND (end IS NOT NULL)) THEN CASE WHEN 
((('now'::text)::date = begin) AND (('now'::text)::date = end)) THEN 
'Active'::text ELSE 'Inactive'::text END WHEN (begin IS NOT NULL) THEN CASE 
WHEN (('now'::text)::date = begin) THEN 'Active'::text ELSE 
'Inactive'::text END WHEN (end IS NOT NULL) THEN CASE WHEN 
(('now'::text)::date = end) THEN 'Active'::text ELSE 'Inactive'::text END 
ELSE 'Active'::text END = 'Active'::text)
  -  Nested Loop Left Join  (cost=0.00..842.19 rows=97 width=175) (actual 
time=6.820..42.863 rows=21 loops=4725)
-  Index Scan using namemaster_programid_idx on namemaster dem  
(cost=0.00..470.12 rows=97 width=164) (actual time=6.811..42.654 rows=21 
loops=4725)
  Index Cond: (programid = 120)
  Filter: ((name_float_lfm ~~* '%clark%'::text) OR 
(metaphone(name_float_lfm, 4) = 'KLRK'::text) OR (soundex(name_float_lfm) = 
'C462'::text))
-  Index Scan using validanswerid_pk on validanswer ina  
(cost=0.00..3.82 rows=1 width=19) (actual time=0.003..0.004 rows=1 
loops=99225)
  Index Cond: (ina.validanswerid = outer.inactive)

-
[2] A much simpler statement triggers the incorrect row counts here.

explain analyze
select * 
from roles rol
where  

CASE
   WHEN rol.role_id IS NULL
   THEN NULL
   WHEN rol.begin IS NOT NULL and rol.end IS NOT NULL
   THEN
 CASE WHEN TIMESTAMP 'now'=rol.begin and TIMESTAMP 
'now'=rol.end
 THEN 'Active'
 ELSE 'Inactive' END
   WHEN rol.begin IS NOT NULL
   THEN
 CASE WHEN TIMESTAMP 'now'=rol.begin
 THEN 'Active'
 ELSE 'Inactive' END
   WHEN rol.end IS NOT NULL
   THEN
 CASE WHEN TIMESTAMP 'now'=rol.end
 THEN 'Active'
 ELSE 'Inactive' END
   ELSE 'Active'
   END = 'Active'

Seq Scan on roles rol  (cost=0.00..2368.54 rows=413 width=20) (actual 
time=0.046..562.635 rows=79424 loops=1)
   Filter: (CASE WHEN (role_id IS NULL) THEN NULL::text WHEN ((begin IS NOT 
NULL) AND (end IS NOT NULL)) THEN CASE WHEN (('2005-09-13 
16:43:18.721214'::timestamp without time zone = begin) AND ('2005-09-13 
16:43:18.721214'::timestamp without time zone = end)) THEN 'Active'::text 
ELSE 'Inactive'::text END WHEN (begin IS NOT NULL) THEN CASE WHEN 
('2005-09-13 16:43:18.721214'::timestamp without time zone = begin) THEN 
'Active'::text ELSE 'Inactive'::text END WHEN (end IS NOT NULL) THEN CASE 
WHEN ('2005-09-13 16:43:18.721214'::timestamp without time zone = end) 
THEN 'Active'::text ELSE 'Inactive'::text END ELSE 'Active'::text END = 
'Active'::text)
 Total runtime: 884.456 ms
(3 rows)
-- 
Chris Kratz

---(end of broadcast)---
TIP 1: if posting/reading through

Re: [PERFORM] Large time difference between explain analyze and normal run

2005-02-10 Thread Chris Kratz
On Thursday 10 February 2005 01:58 pm, Tom Lane wrote:
 Chris Kratz [EMAIL PROTECTED] writes:
  Does anyone have any idea why there be over a 4s difference between
  running the statement directly and using explain analyze?
 
   Aggregate  (cost=9848.12..9848.12 rows=1 width=0) (actual
  time=4841.231..4841.235 rows=1 loops=1)
 -  Seq Scan on answer  (cost=0.00..8561.29 rows=514729 width=0)
  (actual time=0.011..2347.762 rows=530576 loops=1)
   Total runtime: 4841.412 ms

 EXPLAIN ANALYZE's principal overhead is two gettimeofday() kernel calls
 per plan node execution, so 1061154 such calls here.  I infer that
 gettimeofday takes about 4 microseconds on your hardware ... which seems
 a bit slow for modern machines.  What sort of box is it?

   regards, tom lane

OK, that makes sense.

Athlon XP 3000+
1.5G Mem

Is there a way to test the gettimeofday() directly?

---(end of broadcast)---
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]


[PERFORM] Performance Tuning

2005-02-09 Thread Chris Kratz
Hello All,

In contrast to what we hear from most others on this list, we find our 
database servers are mostly CPU bound.  We are wondering if this is because 
we have postgres configured incorrectly in some way, or if we really need 
more powerfull processor(s) to gain more performance from postgres.  

We continue to tune our individual queries where we can, but it seems we still 
are waiting on the db a lot in our app.  When we run most queries, top shows 
the postmaster running at 90%+ constantly during the duration of the request.  
The disks get touched occasionally, but not often.  Our database on disk is 
around 2.6G and most of the working set remains cached in memory, hence the 
few disk accesses.  All this seems to point to the need for faster 
processors.

Our question is simply this, is it better to invest in a faster processor at 
this point, or are there configuration changes to make it faster?  I've done 
some testing with with 4x SCSI 10k and the performance didn't improve, in 
fact it actually was slower the the sata drives marginally.  One of our 
developers is suggesting we should compile postgres from scratch for this 
particular processor, and we may try that.  Any other ideas?

-Chris

On this particular development server, we have:

Athlon XP,3000 
1.5G Mem
4x Sata drives in Raid 0

Postgresql 7.4.5 installed via RPM running on Linux kernel 2.6.8.1

Items changed in the postgresql.conf:

tcpip_socket = true
max_connections = 32
port = 5432
shared_buffers = 12288  # min 16, at least max_connections*2, 8KB each
sort_mem=16384
vacuum_mem = 32768  # min 1024, size in KB
max_fsm_pages = 6   # min max_fsm_relations*16, 6 bytes each
max_fsm_relations = 1000# min 100, ~50 bytes each
effective_cache_size = 115200   # typically 8KB each
random_page_cost = 1# units are one sequential page fetch cost


---(end of broadcast)---
TIP 2: you can get off all lists at once with the unregister command
(send unregister YourEmailAddressHere to [EMAIL PROTECTED])


Re: [PERFORM] Performance Tuning

2005-02-09 Thread Chris Kratz
On Wednesday 09 February 2005 03:38 pm, John Arbash Meinel wrote:
...
 I'm very surprised you are doing RAID 0. You realize that if 1 drive
 goes out, your entire array is toast, right? I would recommend doing
 either RAID 10 (0+1), or even Raid 5 if you don't do a lot of writes.

grin  Yeah, we know.  This is a development server and we drop and reload 
databases regularly (sometimes several times a day).  In this case we don't 
really care about the integrity of the data since it's for our developers to 
test code against.  Also, the system is on a mirrored set of drives.  On our 
live servers we have hardware raid 1 at this point for the data drives.  When 
I/O becomes a bottleneck, we are planning on moving to Raid 10 for the data 
and Raid 1 for the transaction log with as many drives as I can twist arms 
for.  Up to this point it has been easier just to stuff the servers full of 
memory and let the OS cache the db in memory.  We know that at some point 
this will no longer work, but for now it is.

As a side note, I learned something very interesting for our developers here.  
We had been doing a drop database and then a reload off a db dump from our 
live server for test data.  This takes 8-15 minutes depending on the server 
(the one above takes about 8 minutes).  I learned through testing that I can 
use create database template some_other_database and make a duplicate in 
about 2.5 minutes. which is a huge gain for us.  We can load a pristine copy, 
make a duplicate, do our testing on the duplicate, drop the duplicate and 
create a new duplicate in less then five mintes.

Cool.

 Probably most important, though is to look at the individual queries and
 see what they are doing.

 Postgresql 7.4.5 installed via RPM running on Linux kernel 2.6.8.1
 
 Items changed in the postgresql.conf:
 
 tcpip_socket = true
 max_connections = 32
 port = 5432
 shared_buffers = 12288   # min 16, at least max_connections*2, 
 8KB each
 sort_mem=16384
 vacuum_mem = 32768   # min 1024, size in KB
 max_fsm_pages = 6# min max_fsm_relations*16, 6 bytes each
 max_fsm_relations = 1000 # min 100, ~50 bytes each
 effective_cache_size = 115200# typically 8KB each
 random_page_cost = 1 # units are one sequential page fetch cost

 Most of these seem okay to me, but random page cost is *way* too low.
 This should never be tuned below 2.  I think this says an index scan of
 *all* rows is as cheap as a sequential scan of all rows. and that
 should never be true.

You caught me.  I actually tweaked that today after finding a page that 
suggested doing that if the data was mostly in memory.  I have been running 
it at 2, and since we didn't notice any improvement, it will be going back to 
2.  

 What could actually be happening is that you are getting index scans
 when a sequential scan would be faster.

 I don't know what you would see, but what does explain analyze select
 count(*) from blah; say. If it is an index scan, you have your machine
 mistuned. select count(*) always grabs every row, and this is always
 cheaper with a sequential scan.

 John
 =:-
With a random_page_cost set to 1, on a larger table a select count(*) nets 
this...

 QUERY PLAN
--
 Aggregate  (cost=9848.12..9848.12 rows=1 width=0) (actual 
time=4916.869..4916.872 rows=1 loops=1)
   -  Seq Scan on answer  (cost=0.00..8561.29 rows=514729 width=0) (actual 
time=0.011..2624.202 rows=514729 loops=1)
 Total runtime: 4916.942 ms
(3 rows)

Now here is a very curious thing.  If I turn on timing and run the count 
without explain analyze, I get...

 count

 514729
(1 row)

Time: 441.539 ms

How odd.  Running the explain adds 4.5s to it.  Running the explain again goes 
back to almost 5s.  Now I wonder why that would be different.

Changing random cpu cost back to 2 nets little difference (4991.940ms for 
explain and 496ms)  But we will leave it at that for now.

-- 
Chris Kratz
Systems Analyst/Programmer
VistaShare LLC
www.vistashare.com


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

   http://archives.postgresql.org


Re: [PERFORM] Performance Tuning

2005-02-09 Thread Chris Kratz
On Wednesday 09 February 2005 03:59 pm, Greg Stark wrote:
 Chris Kratz [EMAIL PROTECTED] writes:
  We continue to tune our individual queries where we can, but it seems we
  still are waiting on the db a lot in our app.  When we run most queries,
  top shows the postmaster running at 90%+ constantly during the duration
  of the request. The disks get touched occasionally, but not often.  Our
  database on disk is around 2.6G and most of the working set remains
  cached in memory, hence the few disk accesses.  All this seems to point
  to the need for faster processors.

 I would suggest looking at the top few queries that are taking the most
 cumulative time on the processor. It sounds like the queries are doing a
 ton of logical i/o on data that's cached in RAM. A few indexes might cut
 down on the memory bandwidth needed to churn through all that data.

Hmmm, yes we continue to use indexes judiciously.  I actually think we've 
overdone it in some cases since inserts are starting to slow in some critical 
areas.

  Items changed in the postgresql.conf:
  ...
  random_page_cost = 1# units are one sequential page fetch 
  cost

 This makes it nigh impossible for the server from ever making a sequential
 scan when an index would suffice. What query made you do this? What plan
 did it fix?

Yes, it got set back to 2.  I was testing various settings suggested by a 
posting in the archives and that one didn't get reset.

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

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


Re: [PERFORM] Performance Tuning

2005-02-09 Thread Chris Kratz
On Wednesday 09 February 2005 05:08 pm, Merlin Moncure wrote:
  Hello All,
 
  In contrast to what we hear from most others on this list, we find our
  database servers are mostly CPU bound.  We are wondering if this is
  because
  we have postgres configured incorrectly in some way, or if we really

 need

  more powerfull processor(s) to gain more performance from postgres.

 Yes, many apps are not I/O bound (mine isn't).  Here are factors that
 are likely to make your app CPU bound:

 1. Your cache hit ratio is very high
 2. You have a lot of concurrency.
 3. Your queries are complex, for example, doing sorting or statistics
 analysis

For now, it's number 3.  Relatively low usage, but very complex sql.

 4. Your queries are simple, but the server has to process a lot of them
 (transaction overhead becomes significant) sequentially.
 5. You have context switching problems, etc.

 On the query side, you can tune things down considerably...try and keep
 sorting down to a minimum (order on keys, avoid distinct where possible,
 use 'union all', not 'union').  Basically, reduce individual query time.

 Other stuff:
 For complex queries, use views to cut out plan generation.
 For simple but frequently run queries (select a,b,c from t where k), use
 parameterized prepared statements for a 50% cpu savings, this may not be
 an option in some client interfaces.

Prepared statements are not something we've tried yet.  Perhaps we should look 
into that in cases where it makes sense.


 On the hardware side, you will get improvements by moving to Opteron,
 etc.

 Merlin

Well, that's what we were looking for.  

---

It sounds like our configuration as it stands is probably about as good as we 
are going to get with the hardware we have at this point.

We are cpu bound reflecting the fact that we tend to have complex statements 
doing aggregates, sorts and group bys.

The solutions appear to primarily be:
1. Going to faster hardware of which probably Opterons would be about the only 
choice.  And even that probably won't be a huge difference.
2. Moving to more materialized views and prepared statements where we can.
3. Continue to tweak the sql behind our app.

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


[PERFORM] Long running queries degrade performance

2004-04-16 Thread Chris Kratz
Hello all,

My apologies if this is not the right mailing list to ask this question, but 
we are wondering about general performance tuning principles for our main db 
server.

We have a web app with a postgres backend.  Most queries have subsecond 
response times through the web even with high usage.  Every once in awhile 
someone will run either an ad-hoc query or some other long running db 
process.  For some reason, it seems that a small number 3-4 of these jobs 
running in parallel absolutely floors our server.  In monitoring the jobs, 
linux (Kernel 2.4) drops the long running jobs priority, but even so they 
seem to hog the system resources making subsequent requests for everyone else 
very slow.  Our database at this point is almost entirely processor and 
memory bound because it isn't too large to fit most of the working data into 
memory yet.  There is generally little disk activity when this occurs.  

These long running processes are almost always complex select statements, not 
generally inserts or updates.  We continue to monitor and rework the 
bottlenecks, but what is a little scary to us is how easily the database 
becomes almost completely unresponsive with several large jobs running, 
especially since we have a large number of users.  And it only takes one user 
trying to view a page with one of these selects clicking multiple times 
because it doesn't come back quickly to bring our system to it's knees for 
hours.

We are looking to move to Kernel 2.6 and possibly a dedicated multiprocessor 
machine for postgres towards the end of this year.  But, I am wondering if 
there is anything we can do now to increase the interactive performance while 
there are long running selects running as well.  Are there ways to adjust the 
priority of backend processes, or things to tweak to maximize interactive 
throughput for the quick jobs while the long running ones run in the 
background?  Or if worse comes to worse to actually kill long running 
processes without taking down the whole db as we have had to do on occasion.

Our server is a modest 2.4Ghz P4 with mirrored UW SCSI drives and 1G of 
memory.  The db on disk is around 800M and this machine also hosts our web 
app, so there is some contention for the processor.

Does anyone have any suggestions or thoughts on things we could look at? Is a 
multiprocessor box the only answer, or are there other things we should be 
looking at hardware wise.  Thank you for your time.
-- 
Chris Kratz
Systems Analyst/Programmer
VistaShare LLC
www.vistashare.com

---(end of broadcast)---
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]


Re: [PERFORM] Long running queries degrade performance

2004-04-16 Thread Chris Kratz
On Friday 16 April 2004 4:25 pm, Mike Nolan wrote:
 Given the intermittent nature of the problem and its relative brevity
 (5-10 seconds), I don't know whether top offers the granularity needed to
 locate the bottleneck.

Our long running processes run on the order of multiple minutes (sometimes for 
over an hour) and it's expected because the sql can be quite complex over 
somewhat large datasets.  But it's the bringing the server to it's knees, 
that I'm trying to figure out how to address if we can.  In other words, let 
those long running processes run, but somehow still get decent performance 
for quick requests.

Yours reminds me of what used to happen in our apps back when I worked in java 
and the garbage collector kicked in.  Suddenly everything would stop for 
10-15s and then continue on.  Sort of makes you think the app froze for some 
reason.

 It happens on my development system, and I'm the only one on it.  I know
 I've seen it on the production server, but I think it is a bit more
 common on the development server, though that may be a case of which system
 I spend the most time on.  (Also, the production server is 1300 miles away
 with a DSL connection, so I may just be seeing network delays some of
 the time there.)

Interesting.  Have you tried running a processor monitor and seeing if you are 
getting a cpu or disk spike when you get the blips?  Postgres has been pretty 
constant for us in it's average runtime for any particular query.  We do get 
some fluctuation, but I've always attributed that to other things happening 
in the background.  I sometimes run gkrellm off the server just to see 
what's happening on a macro scale.  It's a great early indicator when we are 
getting slammed one way or another (network, memory, processor, disk, etc).  
Plus it shows a couple of seconds of history so you can see blips pretty 
easily.

 My web app traps double-clicks in javascript and ignores all but the first
 one. That's because some of the users have mice that give double-clicks
 even when they only want one click.

Hmmm, never thought of doing that.  Might be interesting to do something like 
that in a few key places where we have problems.

 --
 Mike Nolan

-- 
Chris Kratz
Systems Analyst/Programmer
VistaShare LLC
www.vistashare.com

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


Re: [PERFORM] Delete performance on delete from table with inherited tables

2004-04-05 Thread Chris Kratz
Thanks Stephan and Tom for your responses.  We have been busy, so I haven't 
had time to do any further research on this till yesterday.  I found that the 
large number of triggers on the parent or master table were foreign key 
triggers for each table back to the child tables (update and delete on 
master, insert on child).  The triggers have existed through several versions 
of postgres and as far as we can tell were automatically created using the 
references keyword at inception.

Yesterday I dropped all the current triggers on parent and children and ran a 
script that did an alter table add foreign key constraint to each of the 67 
child tables with update cascade delete cascade.  After this, the delete from 
the parent where no records existed in the child tables was far more 
acceptable.  Instead of taking hours to do the delete, the process ran for 
about 5 minutes on my workstation.  Removing all constraints entirely reduces 
this time to a couple of seconds.  I am currently evaluating if the foreign 
key constraints are worth the performance penalty in this particular case.

To finish up, it appears that the foreign key implementation has changed since 
when these first tables were created in our database.  Dropping the existing 
triggers and re-adding the constraints on each table significantly improved 
performance for us.  I do not know enough of the internals to know why this 
happened.  But our experience seems to prove that the newer implementation of 
foreign keys is more efficient then previous versions.  YMMV

One other item that was brought up was whether the child tables have the fk 
column indexed, and the answer was yes.  Each had a standard btree index on 
the foreign key.   Explain showed nothing as all the time was being spent in 
the triggers.  Time spent in triggers is not shown in the pg 7.3.4 version of 
explain (nor would I necessarily expect it to).

Thanks for your time, expertise and responses.

-Chris

On Tuesday 09 March 2004 7:18 pm, Stephan Szabo wrote:
 On Wed, 3 Mar 2004, Chris Kratz wrote:
  Which certainly points to the triggers being the culprit.  In reading the
  documentation, it seems like the delete from only... statement should
  ignore the constraint triggers.  But it seems quite obvious from the

 Delete from only merely means that children of the table being deleted
 will not have their rows checked against any where conditions and removed
 for that reason.  It does not affect constraint triggers at all.

 Given I'm guessing it's going to be running about 7000 * 67 queries to
 check the validity of the delete for 7000 rows each having 67 foreign
 keys, I'm not sure there's much to do other than hack around the issue
 right now.

 If you're a superuser, you could temporarily hack reltriggers on the
 table's pg_class row to 0, run the delete and then set it back to the
 correct number. I'm guessing from your message that there's never any
 chance of a concurrent transaction putting in a matching row in a way that
 something is marked as deletable when it isn't?

-- 
Chris Kratz
Systems Analyst/Programmer
VistaShare LLC
www.vistashare.com

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


[PERFORM] Delete performance on delete from table with inherited tables

2004-03-09 Thread Chris Kratz
 doesn't show 
the actual time used when analyze is used seems to again point to the after 
delete triggers as being the culprit.

Is there any other way to make this faster then to drop and rebuild all the 
attached constraints?  Is there a way to disable the constraints for a 
single statement.  Because of the unique nature of the data, we know that the 
inherited tables don't need to be inspected.  The table structure has worked 
quite well up till now and we are hoping to not have to drop our foreign keys 
and inheritance if possible.  Any ideas?

Thanks for your time,

-Chris
-- 
Chris Kratz
Systems Analyst/Programmer
VistaShare LLC

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