Re: [HACKERS] Proposal: Multiversion page api (inplace upgrade)

2008-06-11 Thread Stephen Denne
Gregory Stark wrote:
> "Tom Lane" <[EMAIL PROTECTED]> writes:
> 
> > (Likely counterexample: adding collation info to text values.)
> 
> I don't think the argument really needs an example, but I 
> would be pretty
> upset if we proposed tagging every text datum with a 
> collation. Encoding
> perhaps, though that seems like a bad idea to me on 
> performance grounds, but
> collation is not a property of the data at all.

Again not directly related to difficulties upgrading pages...

The recent discussion ...
http://archives.postgresql.org/pgsql-hackers/2008-06/msg00102.php
... mentions keeping collation information together with text data,
however it is referring to keeping it together when processing it,
not when storing the text.

Regards,
Stephen Denne.
--
At the Datamail Group we value teamwork, respect, achievement, client focus, 
and courage. 
This email with any attachments is confidential and may be subject to legal 
privilege.  
If it is not intended for you please advise by replying immediately, destroy it 
and do not 
copy, disclose or use it in any way.

The Datamail Group, through our GoGreen programme, is committed to 
environmental sustainability.  
Help us in our efforts by not printing this email.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__



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


Re: [HACKERS] Core team statement on replication in PostgreSQL

2008-06-03 Thread Stephen Denne
Hannu Krosing wrote:
> The simplest form of synchronous wal shipping would not even need
> postgresql running on slave, just a small daemon which 
> reports when wal
> blocks are a) received and b) synced to disk. 

While that does sound simple, I'd presume that most people would want the 
guarantee of the same version of postgresql installed wherever the logs are 
ending up, with the log receiver speaking the same protocol version as the log 
sender. I imagine that would be most easily achieved through using something 
like the continuously restoring startup mode of current postgresql.

However variations on this kind of daemon can be used to perform testing, 
configuring it to work well, go slow, pause, not respond, disconnect, or fail 
in particular ways, emulating disk full, etc.

Regards,
Stephen Denne.
--
At the Datamail Group we value teamwork, respect, achievement, client focus, 
and courage. 
This email with any attachments is confidential and may be subject to legal 
privilege.  
If it is not intended for you please advise by replying immediately, destroy it 
and do not 
copy, disclose or use it in any way.

The Datamail Group, through our GoGreen programme, is committed to 
environmental sustainability.  
Help us in our efforts by not printing this email.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__



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


Re: [HACKERS] triggers on prepare, commit, rollback... ?

2008-05-20 Thread Stephen Denne
> Tom Lane wrote:
> > Bruce Momjian <[EMAIL PROTECTED]> writes:
> >>>> trigger on "prepare", "commit", "rollback", "savepoint",
> >>> This is a sufficiently frequently asked question that I 
> wish someone 
> >>> would add an entry to the FAQ about it, or add it to the 
> TODO list's 
> >>> "Features we don't want" section.
> > 
> >> OK, remind me why we don't want it again?
> > 
> > I'm sure I've ranted on this several times before, but a 
> quick archive
> > search doesn't find anything.  

I know of this very short "rant":
http://archives.postgresql.org/pgsql-hackers/2008-04/msg01200.php

Florian G. Pflug wrote:
> A possible use-case for that is aggregating some statistics collected 
> during a transaction. One could e.g. maintain a cache of 
> table rowcounts
> by summing up the number of inserted and deleted records per 
> table with 
> some per-row ON INSERT and ON DELETE (presumably C-language) triggers,
> and than update a global cache at transaction end.

This is possible now using deferred constraint triggers (PL/pgSQL is 
sufficient), though better described IMHO as "before prepare" or "before 
commit" rather than "on ...".

Any FAQ addition should mention deferred constraint triggers.

I would expect problems with "after commit" and "after rollback" triggers.

I think that the documentation of when the existing deferred constraint 
triggers run in 2PC/non 2PC could be clarified, and the effects on the 
transaction state that are possible within such trigger functions documented.

http://www.postgresql.org/docs/current/interactive/sql-createconstraint.html

Says

"They can be fired either at the end of the statement causing the triggering 
event, or at the end of the containing transaction;"

It refers to

http://www.postgresql.org/docs/current/interactive/sql-createtable.html

Which says

"Checking of constraints that are deferrable can be postponed until the end of 
the transaction"

and

"If the constraint is INITIALLY DEFERRED, it is checked only at the end of the 
transaction."

I'd also contest this statement:

"Only foreign key constraints currently accept this clause. All other 
constraint types are not deferrable."

Regards,
Stephen Denne.
At the Datamail Group we value teamwork, respect, achievement, client focus, 
and courage. 
This email with any attachments is confidential and may be subject to legal 
privilege.  
If it is not intended for you please advise by replying immediately, destroy it 
and do not 
copy, disclose or use it in any way.

The Datamail Group, through our GoGreen programme, is committed to 
environmental sustainability.  
Help us in our efforts by not printing this email.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__


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


Re: [HACKERS] count(*) performance improvement ideas

2008-04-17 Thread Stephen Denne
> > The big gotcha is that these are all non-transactional 
> > : if you rollback,  
> > GD and SD stay the same, and when you issue a query, you can 
> > assume the  
> > state of SD and GD is random (due to previous queries) unless you  
> > initialize them to a known value.
> 
> Using txid_current() as a key should alleviate that.

No... hold on, it is per session, and a session can't have two or more 
transactions active at once can it?

(Though I hear of things called sub-transactions)

So the problem is that other functions may be using GD themselves, and your own 
code is at the mercy of the other functions. Conversely you shouldn't clear GD, 
as some other function may be using it.

So you're better off using a single function for everything, and using SD 
within it?

There isn't any way of telling whether the function is being called for the 
first time in a transaction. You don't know when to clear it.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__


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


Re: [HACKERS] count(*) performance improvement ideas

2008-04-17 Thread Stephen Denne
PFC wrote
> <[EMAIL PROTECTED]> wrote:
> > I don't know plpythonu (nor python), just read a few docs now:
> 
>   Learn Python, it is a really useful language ;)

My wife has a snake phobia, besides, I've just started learning Scala.


>   There is no sharing between processes, so
>   - both SD and GD are limited to the current session 
> (connection, postgres  
> process), no shared memory is involved
>   - GD is global between all python functions (global)
>   - SD is specific to each python function (static)

Thanks.

>   The big gotcha is that these are all non-transactional 
> : if you rollback,  
> GD and SD stay the same, and when you issue a query, you can 
> assume the  
> state of SD and GD is random (due to previous queries) unless you  
> initialize them to a known value.

Using txid_current() as a key should alleviate that.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__


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


Re: [HACKERS] count(*) performance improvement ideas

2008-04-16 Thread Stephen Denne
PFC wrote:
> Let's try this quick & dirty implementation of a local 
> count-delta cache  
> using a local in-memory hashtable (ie. {}).

> CREATE OR REPLACE FUNCTION update_count( key TEXT, delta INTEGER )
>RETURNS INTEGER
> AS $$
>  if key in GD:
>  GD[key] += delta
>  else:
>  GD[key] = delta
>  return GD[key]
> $$ LANGUAGE plpythonu;

Thanks for the code, this seems to be very much what I was looking for.

I don't know plpythonu (nor python), just read a few docs now:
"The global dictionary SD is available to store data between function calls. 
This variable is private static data. The global dictionary GD is public data, 
available to all Python functions within a session. Use with care."

Does session == transaction or connection?
I don't understand the difference between SD and GD, private and public. Where 
are the context boundaries?

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__


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


Re: [HACKERS] count(*) performance improvement ideas

2008-04-16 Thread Stephen Denne
Tom Lane wrote
> Transaction commit is an exceedingly subtle and carefully structured
> thing.  Throwing random user-defined code into it ain't gonna happen.

Deferred constraint triggers currently run random user-defined code. This'll do 
me.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__



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


Re: [HACKERS] count(*) performance improvement ideas

2008-04-16 Thread Stephen Denne
Tom Lane wrote
> "Stephen Denne" <[EMAIL PROTECTED]> writes:
> > From: Tom Lane [mailto:[EMAIL PROTECTED]
> >> As for 2) and 3), can't you look into the pg_settings view?
> 
> > pg_settings view doesn't contain custom variables created 
> on the fly,
> 
> Really?  [ pokes around ... ]  Hm, you're right, because
> add_placeholder_variable() sets the GUC_NO_SHOW_ALL flag, and in this
> usage it'll never be cleared.  I wonder if we should change that.
> 
> The whole thing is a bit of an abuse of what the mechanism 
> was intended
> for, and so I'm not sure we should rejigger GUC's behavior to make it
> more pleasant, but on the other hand if we're not ready to provide a
> better substitute ...

In my experiments with materialized views, I identified these problems as 
"minor" difficulties. Resolving them would allow further abuse ;)

Aside: It is currently more cumbersome to get a function to run, if needed, at 
commit. Ideal solution would be something like "EXECUTE ON COMMIT 
my_function()" or maybe "SAVEPOINT my_name ON COMMIT my_function()", but these 
suggestions are made without investigating what provision the SQL standard has 
made to address this need.

My use of mv.initialized means I can create variables when initializing a 
transaction, and afterwards know that they have values, but what I can't easily 
do is use those variables to identify which grouping keys have been updated. To 
do that I select & conditionally insert to a table for that explicit purpose. 
If select doesn't find the key, then I create variables named after that key, 
with zero values.

Performance and efficiency-wise which would be better way of keeping track 
of grouping keys used in a transaction?:
1) Create a temp table, on commit drop, for the transaction, storing grouping 
keys affected.
2) Use a persistent table, storing txid and grouping keys affected, deleting 
txid rows at commit.
3) Use pg_settings, storing tx local grouping keys affected, existence check 
via catching an exception, listing via checking existence for all possible 
values (a possibility in my scenario).

Speed is my priority, low disk IO is a probable means to that end, which is why 
I investigated using variables.

Basically, (3) isn't a viable option, so what are the trade-offs between 
creating a temporary table per transaction, or using rows in a permanent table 
with a txid column?

Here are some more plpgsql code fragments:

   mv := 'mv.' || view_name || '.' || key_value || '.';

When recording a grouping key as being affected by the transaction, create the 
variables with zeroes:

   PERFORM set_config(mv||'documents', '0', true);
   PERFORM set_config(mv||'last_addition', 'null', true);

In an insert trigger:

   PERFORM set_config(mv||'documents', 
(current_setting(mv||'documents')::bigint + 1)::text, true);
   PERFORM set_config(mv||'last_addition', now()::text, true);

In the defferred till commit trigger:

  UPDATE materialized_view set 
 documents=documents+current_setting(mv||'documents')::bigint, 
 
last_addition=greatest(last_addition,nullif(current_setting(mv||'last_addition'),'null')::timestamp)
 where 
 group_id = key_values.key_value;


Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__



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


Re: [HACKERS] count(*) performance improvement ideas

2008-04-15 Thread Stephen Denne
(apologies for the email format & top posting, I've had to temporarily switch 
to using a web interface from home that doesn't seem to know what plain text is)
 
pg_settings view doesn't contain custom variables created on the fly, (nor, 
from memory, ones defined in postgresql.conf. I'm not able to check and confirm 
that at the moment).
Fixing that would satisfy 2 & 3 nicely.
The docs on them say the ones in postgresql.conf are to be used by modules when 
they initialize, as the values to use when setting up actual real server 
variables, (able to store more types than just text), which I presume would 
appear in pg_settings.
 
Updating existing variables is much quicker, over 10 updates per second.
 
Regards,
Stephen Denne.



From: Tom Lane [mailto:[EMAIL PROTECTED]
Sent: Wed 16/04/2008 1:55 p.m.

"Stephen Denne" <[EMAIL PROTECTED]> writes:
> The custom variable class can also be used to aggregate the deltas within a 
> transaction, though there are some minor difficulties:

> 1) They only store text
> 2) You can only find out that a value has not been set by catching an 
> exception
> 3) There is no way to list the settings.

As for 2) and 3), can't you look into the pg_settings view?

> The time to create them for the first time for a connection seems to
vary a bit, between 200 and 1000 per minute.

Yeah, that path is not optimized at all because it was never considered
performance-critical.  Updating an existing variable should be cheaper.

regards, tom lane


Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__



Re: [HACKERS] count(*) performance improvement ideas

2008-04-15 Thread Stephen Denne
(There is a possible performance bug mentioned at the end of the email, the 
rest is further discussion regarding materialised views)

I wrote
> Pavan Deolasee wrote
> > On Thu, Mar 20, 2008 at 3:24 AM, Stephen Denne
> > <[EMAIL PROTECTED]> wrote:
> > 
> > >
> > >  Pavan also refers to deferred triggers, which has got me 
> > thinking about another possible solution:
> > >
> > >  Instead of inserting a delta row, that will be updated a 
> > lot of times, create an on commit drop temp table named after 
> > the txid and the grouping value (which is an integer in my 
> > case, perhaps hash it if you're grouping by something that 
> > doesn't easily convert to part of a table name),
> > >  create an after insert initially deferred constraint to 
> > call a function which will move the 'at commit' values of the 
> > rows in the temp table to the summary table.
> > >  The temp table will only have one row inserted, updated 
> > many times, then on commit the trigger is fired once, and the 
> > temp table is dropped.
> > >
> > >  Does anyone think this will or won't work for some reason?
> > 
> > 
> > I think this should work, although you may need to take some 
> > extra steps
> > to manage the summary table. Also, I think a single temp 
> > table per transaction
> > should suffice. The temp table would have one row per "group 
> > by" or "where"
> > condition on which you want to track the count. The 
> > corresponding row will
> > be updated as and when the corresponding count changes. You 
> would need
> > INSERT/DELETE/UPDATE triggers to do that. If there are any 
> > subtransaction
> > aborts, that will be taken care by MVCC.
> 
> Thanks for that. I had gone ahead and tried out the idea, and 
> it was working 'ok'.
> 
> Using one table per transaction has the benefit of less temp 
> tables (but the same number of triggers waiting to run). It 
> also removes the grouping key from the table name.
> 
> I was using a single table per grouping key, with a single 
> updated row in it.
> The benefit was simpler queries, and I could create an ON 
> INSERT trigger that would be triggered only once when the 
> temp table was created, and a 'zero' row was inserted, 
> thereby separating the setup of the trigger from the 
> maintenance of the delta.

One temp table per grouping key would presumably allocate at least one disk 
page per grouping key.
This might result in pretty poor performance. Though if the number of updates 
per grouping key is large, HOT would have plenty of room on the page to write 
new row versions.

Does creation & dropping of temp tables result in system catalog bloat?

> I took a wild guess at a way of finding out whether the temp 
> table already exists:
>   not exists(select tablename from pg_catalog.pg_tables 
> where tablename=temp_delta_txid_group)
> Is there a better/safer way?

Answering my own question:
There is a better way to do what I was doing, (not sure about a better way to 
check existence of a temp table though)...

A custom variable class can be set up and used to record whether the 
transaction in question has been set up. (Thanks to Andreas Kretschmer for 
pointing those out in another thread on -general)

Alter this setting within postgresql.conf to add 'mv':
custom_variable_classes = 'mv'

Add this setting to postgresql.conf:
mv.initialized = 'false'

Then only set it to true local to the transaction.

Usage within a trigger:

   IF NOT (current_setting('mv.initialized')::boolean) THEN
  -- trigger a deferred constraint function:
  INSERT INTO mv_txid_doc_type_summary VALUES (txid_current());
  PERFORM set_config('mv.initialized', 'true', true);
   END IF;

The custom variable class can also be used to aggregate the deltas within a 
transaction, though there are some minor difficulties:

1) They only store text
2) You can only find out that a value has not been set by catching an exception
3) There is no way to list the settings.

The main benefit is that changing a variable's setting does not write a new row 
version.
Creating new transactionally scoped variables seems to take around 150 to 200 
bytes of the process ram per variable, (depending on the size of the value 
stored).
The time to create them for the first time for a connection seems to vary a 
bit, between 200 and 1000 per minute. No IO is being performed, CPU is at 100%
These statistics gathered when trying variations of this query:

select count(*) from (select set_config('mv.test11.' || s1.s1, s2.s2::text, 
true) from (select s1 from generate_series(

Re: [HACKERS] Allow COPY from STDIN to absorb all input before throwing an error

2008-04-08 Thread Stephen Denne
Tom Lane wrote
> Decibel! <[EMAIL PROTECTED]> writes:
> > When restoring from pg_dump(all), if a problem occurs in a COPY  
> > command you're going to get a whole slew of errors, because 
> as soon  
> > as COPY detects a problem it will throw an error and psql will  
> > immediately switch to trying to process the remaining data 
> that was  
> > meant for COPY as if it was psql commands. This is confusing and  
> > annoying at best; it could conceivably trash data at worst 
> (picture  
> > dumping a table that had SQL commands in it).
> 
> This is nonsense; it hasn't worked that way since we went to v3
> protocol.
> 
> What is true is that if the COPY command itself is thoroughly borked,
> the backend never tells psql to switch into COPY mode in the first
> place.

I had an annoying experience with COPY within psql yesterday.
I had a dump of just three tables, which I wanted to investigate. I tried 
loading them into an empty database, using psql's \i command.
The table creation failed as dependent tables/sequences where absent.
The copy command failed as the tables did not exist.
The data intended as the input to the copy statement resulted in a large number 
of error messages.

> > My idea to avoid this situation is to add an option to COPY that  
> > tells it not to throw an error until it runs out of input data.
> 
> This will not solve the problem, since again it only works if the COPY
> command gets to execution.

It is only now that I've found the \set ON_ERROR_STOP command, which I presume 
would have solved my problem.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__



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


Re: [HACKERS] count(*) performance improvement ideas

2008-03-24 Thread Stephen Denne
Pavan Deolasee wrote
> On Thu, Mar 20, 2008 at 3:24 AM, Stephen Denne
> <[EMAIL PROTECTED]> wrote:
> 
> >
> >  Pavan also refers to deferred triggers, which has got me 
> thinking about another possible solution:
> >
> >  Instead of inserting a delta row, that will be updated a 
> lot of times, create an on commit drop temp table named after 
> the txid and the grouping value (which is an integer in my 
> case, perhaps hash it if you're grouping by something that 
> doesn't easily convert to part of a table name),
> >  create an after insert initially deferred constraint to 
> call a function which will move the 'at commit' values of the 
> rows in the temp table to the summary table.
> >  The temp table will only have one row inserted, updated 
> many times, then on commit the trigger is fired once, and the 
> temp table is dropped.
> >
> >  Does anyone think this will or won't work for some reason?
> 
> 
> I think this should work, although you may need to take some 
> extra steps
> to manage the summary table. Also, I think a single temp 
> table per transaction
> should suffice. The temp table would have one row per "group 
> by" or "where"
> condition on which you want to track the count. The 
> corresponding row will
> be updated as and when the corresponding count changes. You would need
> INSERT/DELETE/UPDATE triggers to do that. If there are any 
> subtransaction
> aborts, that will be taken care by MVCC.

Thanks for that. I had gone ahead and tried out the idea, and it was working 
'ok'.

Using one table per transaction has the benefit of less temp tables (but the 
same number of triggers waiting to run). It also removes the grouping key from 
the table name.

I was using a single table per grouping key, with a single updated row in it.
The benefit was simpler queries, and I could create an ON INSERT trigger that 
would be triggered only once when the temp table was created, and a 'zero' row 
was inserted, thereby separating the setup of the trigger from the maintenance 
of the delta.

I haven't explored the transactional implications of updating vs inserting 
delta rows in the summary table at the time of transaction commit. The code 
below updates the summary table, which I think could lead to a large delay or 
deadlocks if there are other styles of updates on that table (other than 
on-commit triggers)?

I also hadn't considered sub-transactions.

Below is a cut-down version of what I tried out.

I was summarizing more than just the number of documents shown below, I was 
storing a sum, and two maximums of timestamps (using the 'greatest' function 
for aggregating each record). These were extra fields in both the summary table 
and the temp tables.
This is able to be made more generic by changing get_temp_table_name() to take 
an additional couple of parameters specifying the name of the function to run 
at commit, and an identifying key (eg 'doc_count' vs 'doc_size_sum'), or 
perhaps including the delta value too, (which looks like it would simplify the 
triggers on the tables whose changes we wish to summarize, except that it 
doesn't cater for storing greatest or least aggregates.)

I took a wild guess at a way of finding out whether the temp table already 
exists:
not exists(select tablename from pg_catalog.pg_tables where 
tablename=temp_delta_txid_group)
Is there a better/safer way?

Here's part of the code I've got at the moment (edited here to cut it down to 
the core example, so it may contain errors):

CREATE TABLE doc_type_summary (
  document_type_id integer NOT NULL,
  documents bigint NOT NULL DEFAULT 0,
  CONSTRAINT pk_doc_type_summary PRIMARY KEY (document_type_id)
);

CREATE OR REPLACE FUNCTION process_delta() RETURNS TRIGGER AS
$$
   BEGIN
  EXECUTE 'UPDATE doc_type_summary set 
documents=doc_type_summary.documents+d.documents from ' || TG_ARGV[0] || ' as d 
where document_type_id = ' || TG_ARGV[1];
  RETURN NULL;
   END;
$$
LANGUAGE 'plpgsql';

CREATE OR REPLACE FUNCTION get_temp_table_name(document_type_id integer)
RETURNS text AS
$$
DECLARE
   temp_delta_txid_group text;
BEGIN
   temp_delta_txid_group := 'temp_delta_' || txid_current() || '_' || 
document_type_id;
   IF not exists(select tablename from pg_catalog.pg_tables where 
tablename=temp_delta_txid_group) THEN
  EXECUTE 'CREATE TEMP TABLE ' || temp_delta_txid_group || '(documents 
bigint NOT NULL DEFAULT 0) ON COMMIT DROP';
  EXECUTE 'CREATE CONSTRAINT TRIGGER ' || temp_delta_txid_group || '_trig 
AFTER INSERT ON ' || temp_delta_txid_group || ' DEFERRABLE INITIALLY DEFERRED 
FOR EACH ROW EXECUTE PROCEDURE process_delta ("'

Re: [HACKERS] count(*) performance improvement ideas

2008-03-19 Thread Stephen Denne
Mark Mielke wrote
> This returns to the question of whether count of the whole table is useful, 
> or whether 
> count of a GROUP BY or WHERE is useful.
> If GROUP BY or WHERE is useful, then trigger on UPDATE becomes necessary.

True... for the example I gave I should have had an update trigger on my table.
I neglected it as I based the example of a more complex multi-table example 
from my application, where I know that the value I'm grouping by doesn't change.

> What is the direction here? Is it count of the whole table only? (<-- not 
> interesting to me)
> Or count of more practical real life examples, which I completely agree with 
> Greg, 
> that this gets into the materialized view realm, and becomes very interesting.
> In my current db project, I never count all of the rows in a table. However, 
> I do use count(*) with GROUP BY and WHERE.

I'm trying to figure out how close I can come to a useful efficient 
materialized view with current production builds of postgresql,
and identifying areas where changes to postgresql could make it easier.

Currently I can see three areas of concern:

1) Turning it on
My query to initially populate the materialized view table takes 6 hours on my 
(limited hardware) development system, which highlights the problem of when do 
you turn on the triggers.
An outage is one way to guarantee that there are neither missing details nor 
double counted details.
Would turning on the triggers and then running my initial population query in 
the same transaction work?

2) Table bloat
I'm trying to group together a large number of +1 or -1 deltas into a single 
delta per transaction.
This creates as many dead rows as there are updates.
This is also a problem with Pavan's suggestion of maintaining a counter table.
They can all be HOT updates in 8.3, but they still all create new row versions.

Tom says "Collapsing a transaction's changes
into a single row would require keeping some intra-transaction state,
which is do-able at the C-code level but not from plpgsql."

So can I hope that this problem is solvable as a contrib module that will work 
with at least 8.3?
I'd still want to write plpgsql trigger function myself, as I know the 
aggregation rules, and call contributed functions to integrate with the 
collapsing of the transaction's changes into a single row. (Expect I'd need a 
small number of rows per transaction, as I need to create delta rows for each 
value of my grouping field involved in the transaction.

3) How to incorporate the deltas.
With my technique, if the transaction rolls back the delta record becomes a 
dead row, if it commits, the delta is then visible to transaction started after 
this time.
I need to have a regular process run to sum and remove the deltas, rewriting 
the summary rows.
I'd like to be able to write an after-commit trigger that fires after changes 
in dependent tables that I identify, which can add the transaction's deltas to 
the summary table. I would want it to effectively be a new, small transaction.

I think that if these three areas are addressed, then before even considering 
writing code to automatically convert any given view into a materialized view.

2) and 3) could perhaps be implemented with a per transaction map from 
my_custom_key to a prepared statement and a list of parameter values.
Provide access to the values, making them updateable within the transaction. 
Have the statement automatically executed on commit.

Pavan also refers to deferred triggers, which has got me thinking about another 
possible solution:

Instead of inserting a delta row, that will be updated a lot of times, create 
an on commit drop temp table named after the txid and the grouping value (which 
is an integer in my case, perhaps hash it if you're grouping by something that 
doesn't easily convert to part of a table name), 
create an after insert initially deferred constraint to call a function which 
will move the 'at commit' values of the rows in the temp table to the summary 
table.
The temp table will only have one row inserted, updated many times, then on 
commit the trigger is fired once, and the temp table is dropped.

Does anyone think this will or won't work for some reason?

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
___

Re: [HACKERS] count(*) performance improvement ideas

2008-03-18 Thread Stephen Denne
Tom Lane wrote
> "Stephen Denne" <[EMAIL PROTECTED]> writes:
> > What I was asking about with those questions, is if a 
> > single row is inserted in transaction A, and updated 1000 
> > times still within transaction A, then transaction A 
> > commits... does a single row version get written, or 1001, 
> > 1000 of which are removable?
> 
> Umm ... AFAICS there is no need for an UPDATE to touch the count table
> at all.  You'd only need ON INSERT and ON DELETE triggers.

I'm not referring to updates of my base table... the single row inserted was 
referring to the delta row...

I'm trying to group together a large number of +1 or -1 deltas into a single 
delta per transaction.

A cut down example:

CREATE TABLE document_type_summary_detail
(
  document_type_id integer NOT NULL,
  txid bigint NOT NULL DEFAULT 0,
  documents bigint NOT NULL DEFAULT 0,
  CONSTRAINT pk_document_type_summary PRIMARY KEY (document_type_id, txid)
);

CREATE OR REPLACE FUNCTION document_count_trig()
RETURNS TRIGGER AS
$$
   DECLARE
   BEGIN
   IF TG_OP = 'INSERT' THEN
  UPDATE document_type_summary_detail set documents=documents+1 where 
document_type_id = NEW.document_type_id and txid=txid_current();
  IF NOT FOUND THEN
 INSERT INTO document_type_summary_detail 
(document_type_id,documents,txid) VALUES(NEW.document_type_id,1,txid_current());
  END IF;
  RETURN NEW;
   ELSIF TG_OP = 'DELETE' THEN
  UPDATE document_type_summary_detail set documents=documents-1 where 
document_type_id = OLD.document_type_id and txid=txid_current();
  IF NOT FOUND THEN
 INSERT INTO document_type_summary_detail 
(document_type_id,documents,txid) 
VALUES(OLD.document_type_id,-1,txid_current());
  END IF;
  RETURN OLD;
   END IF;
   END;
$$
LANGUAGE 'plpgsql';

create trigger document_count_trig before insert or delete on document for each 
row execute procedure document_count_trig();

--one off setup:
insert into document_type_summary_detail (document_type_id,txid,documents)
select dt.id, 0, count(d.id) from document_type dt left join document d on 
d.document_type_id = dt.id
group by 1,2;


--useful view:
CREATE OR REPLACE VIEW document_type_summary AS SELECT document_type_id, 
sum(documents) AS documents FROM document_type_summary_detail GROUP BY 
document_type_id;


--scheduled cleanup:
CREATE OR REPLACE FUNCTION document_type_summary_aggregate() RETURNS void AS
$$
   BEGIN
  INSERT INTO document_type_summary_detail(document_type_id) select 
distinct document_type_id from document_type_summary_detail except select 
document_type_id from document_type_summary_detail where txid=0;
  UPDATE document_type_summary_detail set documents=v.documents from 
document_type_summary as v where document_type_summary_detail.document_type_id 
= v.document_type_id and document_type_summary_detail.txid=0 and exists (select 
1 from document_type_summary_detail ss where ss.document_type_id = 
document_type_summary_detail.document_type_id and ss.txid <> 0);
  DELETE FROM document_type_summary_detail where txid <> 0;
   END;
$$
LANGUAGE 'plpgsql';


My assumption is that this solves the "locking causes serialisation of 
transactions" problem as the only rows updated are those inserted by the same 
transaction.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__



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


Re: [HACKERS] count(*) performance improvement ideas

2008-03-18 Thread Stephen Denne
(Sorry for the repeat email Tom, I forgot the cc's)

Tom Lane wrote:
> "Stephen Denne" <[EMAIL PROTECTED]> writes:
> > I initially thought that what you meant by "having 
> > transactions enter "delta" entries" was that I have a trigger 
> > that would create a row each time it was called, writing how 
> > many records where inserted or deleted. I didn't understand 
> > how this would be much of an improvement, as each of my rows 
> > would contain either +1 or -1.
> 
> Well, ideally you'd aggregate all the deltas caused by a particular
> transaction into one entry in the counting table.  

Yes, that's what I was attempting to do, but without changing the application 
code.

Using txid_current() can do that, so each of a large number of individual 
inserts or deletes within a transaction updates the same delta row for that 
transaction. I haven't found any references to this being a solution, and 
thought it was worth recording.

> > However I'm not after a fast count(*) from table, but more 
> like a fast
> > select grouping_id, count(*) from my_table group by grouping_id
> 
> You could apply the same technique across each group id, though this
> certainly is getting beyond what any built-in feature might offer.

Agreed. I've tried it out now, and am fairly happy with what I've got.

> > Can you clarify the lack of MVCC problems?
> 
> The point there is that the "right answer" actually depends on the
> observer, since each observer might have a different snapshot and
> therefore be able to "see" a different set of committed rows in the
> underlying table.  The multiple-delta table handles this 
> automatically,
> because you can "see" a delta entry if and only if you could "see"
> the underlying-table changes it represents.
> 
> > Does this idea apply with the same efficiency in pre 8.3, 
> non-HOT implementations?
> 
> I didn't claim it was amazingly efficient in any implementation ;-).
> HOT in particular is nearly useless since most rows in the count
> table will never be updated, only inserted and eventually deleted.
> You might get some mileage on the base row, but that'd be about it.
> The count table will need frequent vacuums as well as frequent
> aggregation scans.
> 
> It should beat scanning a large underlying table, but it's hardly
> gonna be free.

What I was asking about with those questions, is if a single row is inserted in 
transaction A, and updated 1000 times still within transaction A, then 
transaction A commits... does a single row version get written, or 1001, 1000 
of which are removable?

I tested this with a small summary table freshly vacuum full'ed.

10 transactions, one after the other, each transaction inserted three delta 
rows, and updates one of them three times, and the other two five times each.
So 3 inserts and 13 updates per transaction.
The updates only affect non-indexed fields in rows created in the same 
transaction.

The next vacuum full found 52 removable row versions.

I repeated the test, and got 13 removable row versions.

I repeated the test again, and got 13 removable row versions.

I repeated just one of the ten transactions, 13 removable row versions.

All inserts and updates are probably in the one page that has a fair bit of 
free space.

Is it possible to update the HOT code to re-use row versions on the same page 
if they were created in the same transaction?

Conclusion: making use of txid_current(), I can get single delta rows with 
deltas of 1, but doing so creates 1 dead row versions.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.
__
  This email has been scanned by the DMZGlobal Business Quality
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/dmzmessaging.htm for details.
__



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


Re: [HACKERS] count(*) performance improvement ideas

2008-03-17 Thread Stephen Denne
 

Tom Lane wrote
> "Pavan Deolasee" <[EMAIL PROTECTED]> writes:
> > I am sure this must have been discussed before.
> 
> Indeed.  Apparently you didn't find the threads in which the idea of
> having transactions enter "delta" entries was discussed?  Solves both
> the locking and the MVCC problems, at the cost that you need to make
> cleanup passes over the counter table fairly often.

I can't find any posts that directly address what I was looking for.

In my situation I have a small number of concurrent transactions with each 
transaction running a large number of single row inserts or deletes.

However I'm not after a fast count(*) from table, but more like a fast
select grouping_id, count(*) from my_table group by grouping_id

I initially thought that what you meant by "having transactions enter "delta" 
entries" was that I have a trigger that would create a row each time it was 
called, writing how many records where inserted or deleted. I didn't understand 
how this would be much of an improvement, as each of my rows would contain 
either +1 or -1.

But I just realised you might mean to include a txid row in my table of deltas, 
and in my trigger insert or update that row where txid = txid_current()
(per grouping_id)

Is that what is recommended?

No locking problems as each transaction is only updating its own rows.

Can you clarify the lack of MVCC problems?
Do new versions of rows get created if the original version of the row was 
created in the current transaction?
Does this idea apply with the same efficiency in pre 8.3, non-HOT 
implementations?
Any advice on creating or avoiding indexes on the tables in question?

I can think of two options for a performing the cleanup passes using current 
functionality:
1) Using Listen/Notify
Issue a notify whenever a new row is inserted for a transaction. They get 
delivered post transaction commit don't they? And not at all on rollback? Have 
an application listening for them, performing the aggregation & cleanup work.
2) Use a schedule, based on local knowledge of expected number of transactions 
over time.

So I'd rephrase Pavan's suggestion as a request to have post-transaction commit 
triggers that have access to (at least) the txid of the transaction that was 
committed.

Suggested syntax is to add the option "TRANSACTION" (or perhaps "COMMIT") to 
the CREATE TRIGGER statement:

CREATE TRIGGER name AFTER INSERT OR UPDATE OR DELETE ON table FOR EACH 
TRANSACTION EXECUTE PROCEDURE funcname ( arguments );

Any of the triggering actions on the specified table ensure that the function 
is called once if the transaction commits.
Requires a new TG_LEVEL.
TG_OP could be the first action triggered.

Would implementing this be extremely difficult due to transferring information 
from within the transaction to outside the transaction?
If so, perhaps I'd get the same benefit from having a trigger set up to fire 
pre-commit (or pre-prepare), and be a part of the transaction.
Would the locking difficulties be reduced as the lock would not be required 
till late in the game, and not held for long?

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__



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


Re: [HACKERS] Estimating geometric distributions

2008-03-11 Thread Stephen Denne
I wrote:
> > I have a field whose distribution of frequencies of values is 
> > roughly geometric, rather than flat.


> My problem is frequent 
> > over-estimation of rows when restricting by this field with 
> > values not known at plan time.


> Is there any facility already in PostgreSQL to help me here?
> 
> Hopefully an index type that I don't know about yet? 
> (Geometric distributions are similar to those found in word 
> count distributions).
> 
> If not... is there any merit in this idea:
> 
> During the analyze process, the geometric mean of sampled 
> rows was calculated, and if determined to be significantly 
> different from the arithmetic mean, stored in a new stats 
> column. When estimating the number of rows that will be 
> returned by queries of the form shown above, if there is a 
> geometric mean stored, use it instead of the arithmetic mean.

I came up with another (much easier) means of adjusting the planners estimation 
of how many rows will be returned:

Increase the number of distinct values in the statistics.
For example:
update pg_statistic set stadistinct=2691 where starelid=29323 and staattnum=2;

I can then pick a number of distinct values such that the effective arithmetic 
mean is equal to what I calculated the geometric mean to be.

Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__



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


Re: [HACKERS] Maximum statistics target

2008-03-10 Thread Stephen Denne
> We could remove the hard limit on statistics target and 
> impose the limit
> instead on the actual size of the arrays. Ie, allow people to 
> specify larger
> sample sizes and discard unreasonably large excess data 
> (possibly warning them
> when that happens).
> 
> That would remove the screw case the original poster had 
> where he needed to
> scan a large portion of the table to see at least one of 
> every value even
> though there were only 169 distinct values.
> 
> -- 
>   Gregory Stark


That was my use case, but I wasn't the OP.

Your suggestion would satisfy what I was trying to do. However, a higher stats 
target wouldn't solve my root problem (how the planner uses the gathered 
stats), and the statistics gathered at 1000 (and indeed at 200) are quite a 
good representation of what is in the table.

I don't like the idea of changing one limit into two limits. Or are you 
suggesting changing the algorithm that determines how many, and which pages to 
analyze, perhaps so that it is adaptive to the results of the analysis as it 
progresses? That doesn't sound easy.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__



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


[HACKERS] Estimating geometric distributions

2008-03-09 Thread Stephen Denne
I wrote:
> I have a field whose distribution of frequencies of values is 
> roughly geometric, rather than flat.
> Total rows = 36 million
> relpages=504864
> Distinct field values in use = 169
> 10 values account for 50% of the rows.
> 41 values account for 90% of the rows.
> 
> After setting statistics target to 1000 for that field, and 
> analyzing the table, the statistics row for that field had 75 
> most frequent values and a histogram with 77 entries in it. 
> Estimating 152 values in total.

"public";"mytable";"myfield";0;4;152;"{202,179,8,181,173,207,6,118,107,205,182,4,54,247,168,77,169,53,120,159,149,174,167,156,148,150,56,108,66,119,5,99,96,175,97,208,1,130,10,102,228,101,121,50,11,152,32,12,78,221,55,244,241,252,203,116,103,184,154,153,238,65,49,220,83,98,111,85,139,242,240,260,7,109,114}";"{0.0836433,0.0781667,0.0738367,0.0598533,0.04629,0.04447,0.0359833,0.0314267,0.0278333,0.0268,0.0251433,0.0244867,0.02438,0.0223433,0.0207567,0.0189667,0.0168833,0.01582,0.0150267,0.0141767,0.0130467,0.0128933,0.0125767,0.0123567,0.0116567,0.0114967,0.01048,0.01037,0.00994667,0.00987667,0.00977667,0.00965333,0.00916333,0.00828667,0.00732667,0.00712,0.00629,0.00624,0.00576667,0.00558667,0.00477667,0.00475333,0.00410333,0.00405667,0.00371667,0.00334667,0.00334,0.00312667,0.00312667,0.00302,0.00300333,0.00295,0.00287333,0.00271,0.00267,0.00240667,0.00224,0.00221333,0.00215333,0.0021,0.00205667,0.00202667,0.00197333,0.00197333,0.00168667,0.00166,0.00159333,0.00159,0.00154667,0.00150333,0.00149,0.0013,0.00132,0.00112667,0.00104}";"{2,9,9,9,67,76,84,84,86,87,87,88,95,100,100,100,104,105,105,110,112,112,128,137,137,138,143,144,144,144,151,155,155,155,157,157,158,171,171,183,185,185,185,185,187,194,199,199,200,200,201,204,204,209,209,214,214,214,214,215,217,225,225,225,229,239,239,249,250,250,253,253,255,257,261,262,266}";0.449246

My problem is frequent 
> over-estimation of rows when restricting by this field with 
> values not known at plan time.

examples:
select * from mytable where myfield = ?;
select * from mytable where myfield in (subquery);

My arithmetic mean of the frequencies is 214200
My geometric mean is 13444

However analyze didn't find all my values, and thinks that there are only 152 
of them, so it uses a mean of 238046


When the subquery is estimated to return three myfield values, the query 
estimates 714138 rows, and chooses a sequential scan over mytable (myfield is 
indexed).

explain select * from mytable where myfield in (values (1),(2),(3));

Hash IN Join  (cost=0.08..1009521.37 rows=714138 width=86)
  Hash Cond: (mytable.myfield = "*VALUES*".column1)
  ->  Seq Scan on mytable  (cost=0.00..866693.76 rows=36182976 width=86)
  ->  Hash  (cost=0.04..0.04 rows=3 width=4)
->  Values Scan on "*VALUES*"  (cost=0.00..0.04 rows=3 width=4)

I think this query is much more likely to return around 4 rows, and a 
Bitmap Index Scan should be used.

explain select * from mytable where myfield in (values (1),(2));

Nested Loop  (cost=4445.11..931383.93 rows=476092 width=86)
  ->  Unique  (cost=0.04..0.04 rows=2 width=4)
->  Sort  (cost=0.04..0.04 rows=2 width=4)
  Sort Key: "*VALUES*".column1
  ->  Values Scan on "*VALUES*"  (cost=0.00..0.03 rows=2 width=4)
  ->  Bitmap Heap Scan on mytable  (cost=4445.08..462716.37 rows=238046 
width=86)
Recheck Cond: (mytable.myfield = "*VALUES*".column1)
->  Bitmap Index Scan on myindex  (cost=0.00..4385.56 rows=238046 
width=0)
  Index Cond: (mytable.myfield = "*VALUES*".column1)

The expected number of loops (2 here, 3 above) through the Bitmap Heap Scan * 
462716.37 > 1009521.37, but the cost estimate is far too high in the general 
case. It should be closer to 26000 per loop if adjusted for my expectation of 
the number of rows, being 13444 per loop. As such, you should need to expect 
close to 40 myfield values being returned by the subquery before choosing a 
sequential scan.

Is there any facility already in PostgreSQL to help me here?

Hopefully an index type that I don't know about yet? (Geometric distributions 
are similar to those found in word count distributions).

If not... is there any merit in this idea:

During the analyze process, the geometric mean of sampled rows was calculated, 
and if determined to be significantly different from the arithmetic mean, 
stored in a new stats column. When estimating the number of rows that will be 
returned by queries of the form shown above, if there is a geometric mean 
stored, use it instead of the arithmetic mean.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  I

Re: [HACKERS] Maximum statistics target

2008-03-09 Thread Stephen Denne
Tom Lane wrote:
> Martijn van Oosterhout <[EMAIL PROTECTED]> writes:
> > On Fri, Mar 07, 2008 at 07:25:25PM +0100, Peter Eisentraut wrote:
> >> What's the problem with setting it to ten million if I 
> have ten million values 
> >> in the table and I am prepared to spend the resources to 
> maintain those 
> >> statistics?
> 
> > That it'll probably take 10 million seconds to calculate the plans
> > using it? I think Tom pointed there are a few places that are O(n^2)
> > the number entries...
> 
> I'm not wedded to the number 1000 in particular --- obviously that's
> just a round number.  But it would be good to see some 
> performance tests
> with larger settings before deciding that we don't need a limit.

I recently encountered a situation where I would have liked to be able to try a 
larger limit (amongst other ideas for improving my situation):

I have a field whose distribution of frequencies of values is roughly 
geometric, rather than flat.
Total rows = 36 million
relpages=504864
Distinct field values in use = 169
10 values account for 50% of the rows.
41 values account for 90% of the rows.

After setting statistics target to 1000 for that field, and analyzing the 
table, the statistics row for that field had 75 most frequent values and a 
histogram with 76 entries in it. Estimating 151 values in total.

For this situation using a larger statistics target should result in more pages 
being read, and a more accurate record of statistics. It shouldn't result in 
significantly more work for the planner.

It wouldn't solve my problem though, which is frequent over-estimation of rows 
when restricting by this field with values not known at plan time.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__



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


Re: [HACKERS] Ad Hoc Indexes

2008-02-18 Thread Stephen Denne
Justin wrote:
> although in both case with and with out indexes the estimate still failed to 
> return the correct number by allot. 

The improvement wasn't to the part of the query that had the bad cost estimate, 
it was to the part that was being performed hundreds of times instead of the 
one time the planner estimated.

The planner still thought it was only going to perform a sequential scan of 
your wooper table once. So even if there had been any Ad Hoc Index creation 
code that had been used to consider creating indexes as part of a plan cost 
estimate, it wouldn't have bothered creating any indexes on wooper.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__



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


Re: [HACKERS] Ad Hoc Indexes

2008-02-18 Thread Stephen Denne
Justin wrote:
> Then why are the estimates so far off?

Perhaps a really high correlation between those records where coitem_status = 
'O' and those records in your date range. The planner estimates 1 row when 
restricting by both restrictions, whereas there where 458. The 1 row was 
probably a result of a small % for status='O' multiplied by a small % for the 
date range.

> If estimates where correct would it improve the performance that much.

Possibly, but a better performance gain might be obtained by rewriting the 
query, changing the case expression to something along the lines of:

coalesce((
select wrkcnt_code || ' Operation Completed :' || cast(wooper_seqnumber 
as text) 
from wooper inner join wrkcnt on wrkcnt_id = wooper_wrkcnt_id
where wooper_rncomplete = true and wooper_wo_id = coitem_order_id
order by wooper_seqnumber desc limit 1
),'No Operation Completed') as LastFinshedOp

regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__



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

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


[HACKERS] Locale vs LIKE

2008-02-12 Thread Stephen Denne
Given the improvements in 8.3 listed in the release notes:
- Improve efficiency of LIKE/ILIKE, especially for multi-byte character sets 
like UTF-8 (Andrew, Itagaki Takahiro)

Does this still hold:
http://www.postgresql.org/docs/8.3/interactive/locale.html

"The drawback of using locales other than C or POSIX in PostgreSQL is its 
performance impact. It slows character handling and prevents ordinary indexes 
from being used by LIKE. For this reason use locales only if you actually need 
them."

i.e. Do I still have to either initdb --locale=C or explicitly use 
text_pattern_ops?

(Queries include predicates of the form [indexed text expression] like "ABC%")

Stephen Denne

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__


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


Re: [HACKERS] Possible future performance improvement: sort updates/deletes by ctid

2008-01-29 Thread Stephen Denne
> At the planner level that would be entirely the wrong way to go about
> it, because that's forcing the equivalent of a nestloop join, which is
> very unlikely to be faster for the numbers of rows that we're talking
> about here.  The reason it looks faster to you is that the benefits of
> updating the document_file rows in ctid order outweigh the 
> costs of the
> dumb join strategy ... but what we want to achieve here is to 
> have both
> benefits, or at least to give the planner the opportunity to make a
> cost-driven decision about what to do.

Ok.

Here are some more data points, using a smaller table, v8.2.6:


Seq Scan on document_file df  (cost=0.00..208480.85 rows=25101 width=662) 
(actual time=0.239..773.834 rows=25149 loops=1)
  SubPlan
->  Index Scan using pk_document_id on document d  (cost=0.00..8.27 rows=1 
width=4) (actual time=0.011..0.015 rows=1 loops=25149)
  Index Cond: (id = $0)
Total runtime: 4492.363 ms



vs


Hash Join  (cost=1048.85..6539.32 rows=25149 width=666) (actual 
time=575.079..1408.363 rows=25149 loops=1)
  Hash Cond: (df.document_id = d.id)
  ->  Seq Scan on document_file df  (cost=0.00..4987.49 rows=25149 width=662) 
(actual time=60.724..824.195 rows=25149 loops=1)
  ->  Hash  (cost=734.49..734.49 rows=25149 width=8) (actual 
time=40.271..40.271 rows=25149 loops=1)
->  Seq Scan on document d  (cost=0.00..734.49 rows=25149 width=8) 
(actual time=0.055..22.559 rows=25149 loops=1)
Total runtime: 34961.504 ms


These are fairly repeatable for me after doing a vacuum full analyze of the two 
tables.


Have I simply not tuned postgres so that it knows it has everything on a single 
old IDE drive, not split over a few sets of raided SSD drives, hence 
random_page_cost should perhaps be larger than 4.0? Would that make the second 
estimate larger than the first estimate?

Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__


---(end of broadcast)---
TIP 7: You can help support the PostgreSQL project by donating at

http://www.postgresql.org/about/donate


Re: [HACKERS] Possible future performance improvement: sort updates/deletes by ctid

2008-01-29 Thread Stephen Denne
> From: Tom Lane [mailto:[EMAIL PROTECTED] 
> doubtless-oversimplified
It looks equivalent.

> With that patch, I got the results
...
>->  Hash Join  (cost=123330.50..1207292.72 rows=408 
> width=618) (actual time=20186.510..721120.455 rows=400 loops=1)

The plan from here is equivalent to the query plan that I had.
In an update query, does the actual time = 721120 mean that after 12 minutes it 
had completed figuring out what to update, and what to?

> This is with default shared_buffers (32MB) and work_mem (1MB);

I had tried a few larger settings, and though I had fewer temp files created, 
they still took longer than I was willing to wait to process.
I did figure out that contention with the background writer or checkpoint 
processing probably wasn't a large contributor.

How hard is it to match, recognise potential benefit, and rewrite the query from

UPDATE ONLY document_file AS df SET document_type_id = 
d.document_type_id FROM document AS d WHERE d.id = document_id;

to

UPDATE ONLY document_file AS df SET document_type_id = 
(SELECT d.document_type_id FROM document AS d WHERE d.id = document_id);

Which is several orders of magnitude faster for me.

Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__


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


Re: [HACKERS] 8.3RC1 on windows missing descriptive Event handle names

2008-01-29 Thread Stephen Denne
I said...
> On Windows XP, using Process Explorer with the lower pane 
> showing Handles, not all postgres.exe processes are including 
> an "Event" type with a description of what the process is doing.

I've had difficulty reproducing this, but I now suspect that it is only 
happening when running both v8.2 and v8.3rc1 at once, and I think it is the 
second started that is missing the process descriptions.

Regards,
Stephen Denne.

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__


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


Re: [HACKERS] [PATCHES] Proposed patch: synchronized_scanningGUCvariable

2008-01-29 Thread Stephen Denne
Jeff Davis wrote
> > Well clusteredness is used or could be used for a few 
> different heuristics,
> > not all of which this would be quite as well satisfied as 
> readahead. But for
> 
> Can you give an example? Treating a file as a circular structure does
> not impose any significant cost that I can see.

(Pure speculation follows... if you prefer facts, skip this noise)

The data used to create pg_stats.correlation is involved in estimating the cost 
of an index scan.
It could also be used in estimating the cost of a sequential scan, if the query 
includes a limit.

Consider:
select * from huge_table_clustered_by_A where Ahttp://www.dmzglobal.com/services/bqem.htm for details.
__


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


[HACKERS] 8.3RC1 on windows missing descriptive Event handle names

2008-01-14 Thread Stephen Denne
On Windows XP, using Process Explorer with the lower pane showing Handles, not 
all postgres.exe processes are including an "Event" type with a description of 
what the process is doing.

At the moment, I have ten postgres processes shown as being at the bottom of 
the tree, three of which do not have such descriptions.

The processes that do show an Event type handle show these names:

\BaseNamedObjects\pgident: postgres: wal writer process
\BaseNamedObjects\pgident: postgres: autovacuum launcher process

plus one per connection like:

\BaseNamedObjects\pgident: postgres: postgres mydatabase 127.0.0.1(1954) idle


Comparing the list of processes to those of 8.2, I suspect that the processes 
missing this detail are the log writer (one of the processes does have a File 
Handle on the log file), and the stats collector.

I have autovacuum enabled for 8.3rc1, and disabled for 8.2.

PostgreSQL is started as a service.

Stephen Denne

Disclaimer:
At the Datamail Group we value team commitment, respect, achievement, customer 
focus, and courage. This email with any attachments is confidential and may be 
subject to legal privilege.  If it is not intended for you please advise by 
reply immediately, destroy it and do not copy, disclose or use it in any way.

__
  This email has been scanned by the DMZGlobal Business Quality 
  Electronic Messaging Suite.
Please see http://www.dmzglobal.com/services/bqem.htm for details.
__


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