Re: [PERFORM] large dataset with write vs read clients

2010-10-09 Thread Florian Weimer
* Greg Smith:

> Given the size of your database, I'd advise you consider a migration
> to a new version ASAP.  8.4 is a nice stable release at this point,
> that's the one to consider moving to.

It also offers asynchronous commits, which might be a good tradeoff
here (especially if the data gathered is not used for billing purposes
8-).

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



Re: [PERFORM] large dataset with write vs read clients

2010-10-09 Thread Mladen Gogala
I have a logical problem with asynchronous commit. The "commit" command 
should instruct the database to make the outcome of the transaction 
permanent. The application should wait to see whether the commit was 
successful or not. Asynchronous behavior in the commit statement breaks 
the ACID rules and should not be used in a RDBMS system. If you don't 
need ACID, you may not need RDBMS at all. You may try with MongoDB. 
MongoDB is web scale: http://www.youtube.com/watch?v=b2F-DItXtZs


Florian Weimer wrote:

* Greg Smith:

  

Given the size of your database, I'd advise you consider a migration
to a new version ASAP.  8.4 is a nice stable release at this point,
that's the one to consider moving to.



It also offers asynchronous commits, which might be a good tradeoff
here (especially if the data gathered is not used for billing purposes
8-).

  



--
Mladen Gogala 
Sr. Oracle DBA

1500 Broadway
New York, NY 10036
(212) 329-5251
www.vmsinfo.com 



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


[PERFORM] Slow count(*) again...

2010-10-09 Thread Neil Whelchel
I know that there haven been many discussions on the slowness of count(*) even 
when an index is involved because the visibility of the rows has to be 
checked. In the past I have seen many suggestions about using triggers and 
tables to keep track of counts and while this works fine in a situation where 
you know what the report is going to be ahead of time, this is simply not an 
option when an unknown WHERE clause is to be used (dynamically generated).
I ran into a fine example of this when I was searching this mailing list, 
"Searching in 856,646 pages took 13.48202 seconds. Site search powered by 
PostgreSQL 8.3." Obviously at some point count(*) came into play here because 
the site made a list of pages (1 2 3 4 5 6 > next). I very commonly make a 
list of pages from search results, and the biggest time killer here is the 
count(*) portion, even worse yet, I sometimes have to hit the database with 
two SELECT statements, one with OFFSET and LIMIT to get the page of results I 
need and another to get the amount of total rows so I can estimate how many 
pages of results are available. The point I am driving at here is that since 
building a list of pages of results is such a common thing to do, there need 
to be some specific high speed ways to do this in one query. Maybe an 
estimate(*) that works like count but gives an answer from the index without 
checking visibility? I am sure that this would be good enough to make a page 
list, it is really no big deal if it errors on the positive side, maybe the 
list of pages has an extra page off the end. I can live with that. What I 
can't live with is taking 13 seconds to get a page of results from 850,000 
rows in a table.
-Neil-

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


Re: [PERFORM] Slow count(*) again...

2010-10-09 Thread Scott Marlowe
On Sat, Oct 9, 2010 at 5:26 PM, Neil Whelchel  wrote:
> I know that there haven been many discussions on the slowness of count(*) even
> when an index is involved because the visibility of the rows has to be
> checked. In the past I have seen many suggestions about using triggers and
> tables to keep track of counts and while this works fine in a situation where
> you know what the report is going to be ahead of time, this is simply not an
> option when an unknown WHERE clause is to be used (dynamically generated).
> I ran into a fine example of this when I was searching this mailing list,
> "Searching in 856,646 pages took 13.48202 seconds. Site search powered by
> PostgreSQL 8.3." Obviously at some point count(*) came into play here because
> the site made a list of pages (1 2 3 4 5 6 > next). I very commonly make a
> list of pages from search results, and the biggest time killer here is the
> count(*) portion, even worse yet, I sometimes have to hit the database with
> two SELECT statements, one with OFFSET and LIMIT to get the page of results I
> need and another to get the amount of total rows so I can estimate how many
> pages of results are available. The point I am driving at here is that since
> building a list of pages of results is such a common thing to do, there need
> to be some specific high speed ways to do this in one query. Maybe an
> estimate(*) that works like count but gives an answer from the index without
> checking visibility? I am sure that this would be good enough to make a page
> list, it is really no big deal if it errors on the positive side, maybe the
> list of pages has an extra page off the end. I can live with that. What I
> can't live with is taking 13 seconds to get a page of results from 850,000
> rows in a table.

99% of the time in the situations you don't need an exact measure, and
assuming analyze has run recently, select rel_tuples from pg_class for
a given table is more than close enough.  I'm sure wrapping that in a
simple estimated_rows() function would be easy enough to do.

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


Re: [PERFORM] Slow count(*) again...

2010-10-09 Thread Mladen Gogala

Neil Whelchel wrote:
I know that there haven been many discussions on the slowness of count(*) even 
when an index is involved because the visibility of the rows has to be 
checked. In the past I have seen many suggestions about using triggers and 
tables to keep track of counts and while this works fine in a situation where 
you know what the report is going to be ahead of time, this is simply not an 
option when an unknown WHERE clause is to be used (dynamically generated).
I ran into a fine example of this when I was searching this mailing list, 
"Searching in 856,646 pages took 13.48202 seconds. Site search powered by 
PostgreSQL 8.3." Obviously at some point count(*) came into play here because 
the site made a list of pages (1 2 3 4 5 6 > next). I very commonly make a 
list of pages from search results, and the biggest time killer here is the 
count(*) portion, even worse yet, I sometimes have to hit the database with 
two SELECT statements, one with OFFSET and LIMIT to get the page of results I 
need and another to get the amount of total rows so I can estimate how many 
pages of results are available. The point I am driving at here is that since 
building a list of pages of results is such a common thing to do, there need 
to be some specific high speed ways to do this in one query. Maybe an 
estimate(*) that works like count but gives an answer from the index without 
checking visibility? I am sure that this would be good enough to make a page 
list, it is really no big deal if it errors on the positive side, maybe the 
list of pages has an extra page off the end. I can live with that. What I 
can't live with is taking 13 seconds to get a page of results from 850,000 
rows in a table.

-Neil-

  
Unfortunately, the problem is in the rather primitive way PostgreSQL 
does I/O. It didn't change in 9.0 so there is nothing you could gain by 
upgrading. If you execute strace -o /tmp/pg.out -e read sequential scan process> and inspect the file /tmp/pg.out when the query 
finishes, you will notice a gazillion of read requests, all of them 8192 
bytes in size. That means that PostgreSQL is reading the table block by 
block, without any merging of the requests. You can alleviate the pain 
by using the OS tricks, like specifying the deadline I/O scheduler in 
the grub.conf and set prefetch on the FS block devices by using 
blockdev, but there is nothing special that can be done, short of 
rewriting the way PostgreSQL does I/O. There were rumors about the 
version 9.0 and asynchronous I/O, but that didn't materialize. That is 
really strange to me, because PostgreSQL tables are files or groups of 
files, if the table size exceeds 1GB. It wouldn't be very hard to try 
reading 1MB at a time and that would speed up the full table scan 
significantly.
Problem with single block I/O is that there is a context switch for each 
request, the I/O scheduler has to work hard to merge requests 
appropriately and there is really no need for that, tables are files 
navigating through files is not a problem, even with much larger blocks.
In another database, whose name I will not mention, there is a parameter 
db_file_multiblock_read_count which specifies how many blocks will be 
read by a single read when doing a full table scan. PostgreSQL is in 
dire need of something similar and it wouldn't even be that hard to 
implement.



--
Mladen Gogala 
Sr. Oracle DBA

1500 Broadway
New York, NY 10036
(212) 329-5251
www.vmsinfo.com 



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


Re: [PERFORM] Slow count(*) again...

2010-10-09 Thread Joe Conway
On 10/09/2010 06:54 PM, Mladen Gogala wrote:
> In another database, whose name I will not mention, there is a parameter
> db_file_multiblock_read_count which specifies how many blocks will be
> read by a single read when doing a full table scan. PostgreSQL is in
> dire need of something similar and it wouldn't even be that hard to
> implement.

You're correct in that it isn't particularly difficult to implement for
sequential scans. But I have done some testing with aggressive read
ahead, and although it is clearly a big win with a single client, the
benefit was less clear as concurrency was increased.

Joe

-- 
Joe Conway
credativ LLC: http://www.credativ.us
Linux, PostgreSQL, and general Open Source
Training, Service, Consulting, & 24x7 Support



signature.asc
Description: OpenPGP digital signature


Re: [PERFORM] Slow count(*) again...

2010-10-09 Thread Mladen Gogala

Joe Conway wrote:

On 10/09/2010 06:54 PM, Mladen Gogala wrote:
  

In another database, whose name I will not mention, there is a parameter
db_file_multiblock_read_count which specifies how many blocks will be
read by a single read when doing a full table scan. PostgreSQL is in
dire need of something similar and it wouldn't even be that hard to
implement.



You're correct in that it isn't particularly difficult to implement for
sequential scans. But I have done some testing with aggressive read
ahead, and although it is clearly a big win with a single client, the
benefit was less clear as concurrency was increased.

Joe

  
Well, in my opinion that should be left to the DBA, the same as in the 
"other database".  The mythical DBA, the creature that mighty Larry 
Ellison himself is on a crusade against, usually can  figure out the 
right value for the database he or she's is in charge of. I humbly 
confess to being an Oracle DBA for more than 2 decades and now branching 
into Postgres because my employer is less than enthusiastic about 
Oracle, with the special accent on their pricing.


Modern databases, Postgres included, are quite complex and companies 
need DBA personnel to help fine tune the applications. I know that good 
DBA personnel is quite expensive but without a competent DBA who knows 
the database software well enough,  companies can and will suffer from 
blunders with performance, downtime, lost data and alike. In the world 
where almost every application is written for the web, performance, 
uptime and user experience are of the critical importance. The 
architects of Postgres database would be well advised to operate under 
the assumption that every production database has a competent DBA 
keeping an eye on the database.


Every application has its own mix of sequential and index scans, you 
cannot possibly test all possible applications.  Aggressive read-ahead 
or "multi-block reads" can be a performance problem and it will 
complicate the optimizer, because the optimizer now has a new variable  
to account for: the block size, potentially making  seq_page_cost even 
cheaper and random_page_cost even more expensive, depending on the 
blocking. However,  slow sequential scan is, in my humble opinion, the 
single biggest performance problem of the PostgreSQL databases and 
should be improved, the sooner, the better. You should, however, count 
on the DBA personnel to help with the tuning.

We're the Tinkerbells of the database world. I am 6'4", 240 LBS, no wings.


--
Mladen Gogala 
Sr. Oracle DBA

1500 Broadway
New York, NY 10036
(212) 329-5251
www.vmsinfo.com 



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


Re: [PERFORM] Slow count(*) again...

2010-10-09 Thread Neil Whelchel
On Saturday 09 October 2010 18:47:34 Scott Marlowe wrote:
> On Sat, Oct 9, 2010 at 5:26 PM, Neil Whelchel  
wrote:
> > I know that there haven been many discussions on the slowness of count(*)
> > even when an index is involved because the visibility of the rows has to
> > be checked. In the past I have seen many suggestions about using
> > triggers and tables to keep track of counts and while this works fine in
> > a situation where you know what the report is going to be ahead of time,
> > this is simply not an option when an unknown WHERE clause is to be used
> > (dynamically generated). I ran into a fine example of this when I was
> > searching this mailing list, "Searching in 856,646 pages took 13.48202
> > seconds. Site search powered by PostgreSQL 8.3." Obviously at some point
> > count(*) came into play here because the site made a list of pages (1 2
> > 3 4 5 6 > next). I very commonly make a list of pages from search
> > results, and the biggest time killer here is the count(*) portion, even
> > worse yet, I sometimes have to hit the database with two SELECT
> > statements, one with OFFSET and LIMIT to get the page of results I need
> > and another to get the amount of total rows so I can estimate how many
> > pages of results are available. The point I am driving at here is that
> > since building a list of pages of results is such a common thing to do,
> > there need to be some specific high speed ways to do this in one query.
> > Maybe an estimate(*) that works like count but gives an answer from the
> > index without checking visibility? I am sure that this would be good
> > enough to make a page list, it is really no big deal if it errors on the
> > positive side, maybe the list of pages has an extra page off the end. I
> > can live with that. What I can't live with is taking 13 seconds to get a
> > page of results from 850,000 rows in a table.
> 
> 99% of the time in the situations you don't need an exact measure, and
> assuming analyze has run recently, select rel_tuples from pg_class for
> a given table is more than close enough.  I'm sure wrapping that in a
> simple estimated_rows() function would be easy enough to do.

This is a very good approach and it works very well when you are counting the 
entire table, but when you have no control over the WHERE clause, it doesn't 
help. IE: someone puts in a word to look for in a web form.

>From my perspective, this issue is the biggest problem there is when using 
Postgres to create web pages, and it is so commonly used, I think that there 
should be a specific way to deal with it so that you don't have to run the 
same WHERE clause twice. 
IE: SELECT count(*) FROM  WHERE ; to get the total amount of 
items to make page navigation links, then:
SELECT  FROM table WHERE  LIMIT  OFFSET 
<(page_no-1)*items_per_page>; to get the actual page contents.
 
It's bad enough that count(*) is slow, then you have to do it all over again 
to get the results you need! I have not dug into this much yet, but would it 
be possible to return the amount of rows that a WHERE clause would actually 
return if the LIMIT and OFFSET were not applied. IE: When a normal query is 
executed, the server returns the number of rows aside from the actual row 
data. Would it be a big deal to modify this to allow it to return the amount 
of rows before the LIMIT and OFFSET is applied as well? This would sure cut 
down on time it takes to do the same WHERE clause twice... I have considered 
using a cursor to do this, however this requires a transfer of all of the rows 
to the client to get a total count, then setting the cursor to get the rows 
that you are interested in. Or is there a way around this that I am not aware 
of?
-Neil-


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


Re: [PERFORM] Slow count(*) again...

2010-10-09 Thread Samuel Gendler
On Sat, Oct 9, 2010 at 7:44 PM, Mladen Gogala wrote:

>  The architects of Postgres database would be well advised to operate under
> the assumption that every production database has a competent DBA keeping an
> eye on the database.
>

I'd actually go so far as to say that they have already made this
assumption.  The out of the box config needs modification for all but the
most low-volume applications and postgres really benefits from having some
attention paid to performance.  Not only does tuning the db provide enormous
gains, but it is often possible to dramatically improve query responsiveness
by simply restructuring a query (assuming an aggregating query over a fairly
large table with a few joins thrown in).  My team does not have a competent
DBA (though I've got 15+ years of experience developing on top of various
dbs and certainly don't make overly naive assumptions about how things work)
and the gains that we made, when I finally just sat down and read everything
I could get my hands on about postgres and started reading this list, were
really quite impressive.  I intend to take some of the courses offered by
some of the companies that are active on this list when my schedule allows
in order to expand my knowledge even farther, as a DBA is a luxury we cannot
really afford at the moment.


Re: [PERFORM] large dataset with write vs read clients

2010-10-09 Thread Craig Ringer

On 10/10/2010 5:35 AM, Mladen Gogala wrote:

I have a logical problem with asynchronous commit. The "commit" command
should instruct the database to make the outcome of the transaction
permanent. The application should wait to see whether the commit was
successful or not. Asynchronous behavior in the commit statement breaks
the ACID rules and should not be used in a RDBMS system. If you don't
need ACID, you may not need RDBMS at all. You may try with MongoDB.
MongoDB is web scale: http://www.youtube.com/watch?v=b2F-DItXtZs


That argument makes little sense to me.

Because you can afford a clearly defined and bounded loosening of the 
durability guarantee provided by the database, such that you know and 
accept the possible loss of x seconds of work if your OS crashes or your 
UPS fails, this means you don't really need durability guarantees at all 
- let alone all that atomic commit silliness, transaction isolation, or 
the guarantee of a consistent on-disk state?


Some of the other flavours of non-SQL databases, both those that've been 
around forever (PICK/UniVerse/etc, Berkeley DB, Cache, etc) and those 
that're new and fashionable Cassandra, CouchDB, etc, provide some ACID 
properties anyway. If you don't need/want an SQL interface to your 
database you don't have to throw out all that other database-y goodness 
if you haven't been drinking too much of the NoSQL kool-aid.


There *are* situations in which it's necessary to switch to relying on 
distributed, eventually-consistent databases with non-traditional 
approaches to data management. It's awfully nice not to have to, though, 
and can force you to do a lot more wheel reinvention when it comes to 
querying, analysing and reporting on your data.


FWIW, a common approach in this sort of situation has historically been 
- accepting that RDBMSs aren't great at continuous fast loading of 
individual records - to log the records in batches to a flat file, 
Berkeley DB, etc as a staging point. You periodically rotate that file 
out and bulk-load its contents into the RDBMS for analysis and 
reporting. This doesn't have to be every hour - every minute is usually 
pretty reasonable, and still gives your database a much easier time 
without forcing you to modify your app to batch inserts into 
transactions or anything like that.


--
Craig Ringer

Tech-related writing at http://soapyfrogs.blogspot.com/

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


Re: [PERFORM] large dataset with write vs read clients

2010-10-09 Thread Mladen Gogala

 On 10/10/2010 2:43 AM, Craig Ringer wrote:


Some of the other flavours of non-SQL databases, both those that've been
around forever (PICK/UniVerse/etc, Berkeley DB, Cache, etc) and those
that're new and fashionable Cassandra, CouchDB, etc, provide some ACID
properties anyway. If you don't need/want an SQL interface to your
database you don't have to throw out all that other database-y goodness
if you haven't been drinking too much of the NoSQL kool-aid.
This is a terrible misunderstanding. You haven't taken a look at that 
Youtube clip I sent you, have you? I am an Oracle DBA, first and 
foremost, disturbing the peace since 1989. I haven't been drinking the 
NoSQL kool-aid at all.
I was simply being facetious. ACID rules are business rules and I am 
bitterly opposed to relaxing them. BTW, my favorite drink is Sam Adams Ale.


--
Mladen Gogala
Sr. Oracle DBA
1500 Broadway
New York, NY 10036
(212) 329-5251
www.vmsinfo.com


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


Re: [PERFORM] Slow count(*) again...

2010-10-09 Thread Craig Ringer

On 10/10/2010 11:02 AM, Neil Whelchel wrote:

On Saturday 09 October 2010 18:47:34 Scott Marlowe wrote:

On Sat, Oct 9, 2010 at 5:26 PM, Neil Whelchel

wrote:

I know that there haven been many discussions on the slowness of count(*)
even when an index is involved because the visibility of the rows has to
be checked. In the past I have seen many suggestions about using
triggers and tables to keep track of counts and while this works fine in
a situation where you know what the report is going to be ahead of time,
this is simply not an option when an unknown WHERE clause is to be used
(dynamically generated). I ran into a fine example of this when I was
searching this mailing list, "Searching in 856,646 pages took 13.48202
seconds. Site search powered by PostgreSQL 8.3." Obviously at some point
count(*) came into play here because the site made a list of pages (1 2
3 4 5 6>  next). I very commonly make a list of pages from search
results, and the biggest time killer here is the count(*) portion, even
worse yet, I sometimes have to hit the database with two SELECT
statements, one with OFFSET and LIMIT to get the page of results I need
and another to get the amount of total rows so I can estimate how many
pages of results are available. The point I am driving at here is that
since building a list of pages of results is such a common thing to do,
there need to be some specific high speed ways to do this in one query.
Maybe an estimate(*) that works like count but gives an answer from the
index without checking visibility? I am sure that this would be good
enough to make a page list, it is really no big deal if it errors on the
positive side, maybe the list of pages has an extra page off the end. I
can live with that. What I can't live with is taking 13 seconds to get a
page of results from 850,000 rows in a table.


99% of the time in the situations you don't need an exact measure, and
assuming analyze has run recently, select rel_tuples from pg_class for
a given table is more than close enough.  I'm sure wrapping that in a
simple estimated_rows() function would be easy enough to do.


This is a very good approach and it works very well when you are counting the
entire table, but when you have no control over the WHERE clause, it doesn't
help. IE: someone puts in a word to look for in a web form.


For that sort of thing, there isn't much that'll help you except 
visibility-aware indexes, covering indexes, etc if/when they're 
implemented. Even then, they'd only help when it was a simple 
index-driven query with no need to hit the table to recheck any test 
conditions, etc.


I guess there could be *some* way to expose the query planner's cost 
estimates in a manner useful for result count estimation ... but given 
how coarse its stats are and how wildly out the estimates can be, I kind 
of doubt it. It's really intended for query planning decisions and more 
interested in orders of magnitude, "0, 1, or more than that" measures, 
etc, and seems to consider 30% here or there to be pretty insignificant 
most of the time.



It's bad enough that count(*) is slow, then you have to do it all over again
to get the results you need! I have not dug into this much yet, but would it
be possible to return the amount of rows that a WHERE clause would actually
return if the LIMIT and OFFSET were not applied. IE: When a normal query is
executed, the server returns the number of rows aside from the actual row
data. Would it be a big deal to modify this to allow it to return the amount
of rows before the LIMIT and OFFSET is applied as well?


It'd force the server to fully execute the query. Then again, it sounds 
like you're doing that anyway.


--
Craig Ringer

Tech-related writing at http://soapyfrogs.blogspot.com/

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