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 ("' || temp_delta_txid_group || 
'", ' || document_type_id || ')';
      EXECUTE 'INSERT INTO ' || temp_delta_txid_group || ' DEFAULT VALUES';
   END IF;
   RETURN temp_delta_txid_group;
END;
$$
LANGUAGE 'plpgsql';

CREATE OR REPLACE FUNCTION document_count_trig()
RETURNS TRIGGER AS
$$
DECLARE
   temp_delta_txid_group text;
BEGIN
   IF TG_OP = 'INSERT' THEN
      temp_delta_txid_group := get_temp_table_name(NEW.document_type_id);
      EXECUTE 'UPDATE ' || temp_delta_txid_group || ' set 
documents=documents+1';
      RETURN NEW;
   ELSIF TG_OP = 'DELETE' THEN
      temp_delta_txid_group := get_temp_table_name(OLD.document_type_id);
      EXECUTE 'UPDATE ' || temp_delta_txid_group || ' set 
documents=documents-1';
      RETURN OLD;
   END IF;
END;
$$
LANGUAGE 'plpgsql';

--
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

Reply via email to