Commit b246510c authored by Tom Lane's avatar Tom Lane

Avoid O(N^2) behavior in deferredTriggerAddEvent() for large numbers of

tuples inserted/deleted/updated in a single transaction.  On my machine,
this reduced the time to delete 80000 tuples in a foreign-key-referencing
table from ~15min to ~8sec.
parent 74c732cb
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.86 2001/01/27 05:16:58 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.87 2001/03/12 23:02:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1152,14 +1152,16 @@ static bool deftrig_all_isdeferred; ...@@ -1152,14 +1152,16 @@ static bool deftrig_all_isdeferred;
static List *deftrig_trigstates; static List *deftrig_trigstates;
/* ---------- /* ----------
* The list of events during the entire transaction. * The list of events during the entire transaction. deftrig_events
* is the head, deftrig_event_tail is the last entry.
* *
* XXX This must finally be held in a file because of the huge * XXX Need to be able to shove this data out to a file if it grows too
* number of events that could occur in the real world. * large...
* ---------- * ----------
*/ */
static int deftrig_n_events; static int deftrig_n_events;
static List *deftrig_events; static List *deftrig_events;
static List *deftrig_event_tail;
/* ---------- /* ----------
...@@ -1235,7 +1237,22 @@ deferredTriggerCheckState(Oid tgoid, int32 itemstate) ...@@ -1235,7 +1237,22 @@ deferredTriggerCheckState(Oid tgoid, int32 itemstate)
static void static void
deferredTriggerAddEvent(DeferredTriggerEvent event) deferredTriggerAddEvent(DeferredTriggerEvent event)
{ {
deftrig_events = lappend(deftrig_events, event); /*
* Since the event list could grow quite long, we keep track of the
* list tail and append there, rather than just doing a stupid "lappend".
* This avoids O(N^2) behavior for large numbers of events.
*/
if (deftrig_event_tail == NIL)
{
/* first list entry */
deftrig_events = makeList1(event);
deftrig_event_tail = deftrig_events;
}
else
{
lnext(deftrig_event_tail) = makeList1(event);
deftrig_event_tail = lnext(deftrig_event_tail);
}
deftrig_n_events++; deftrig_n_events++;
} }
...@@ -1397,7 +1414,6 @@ deferredTriggerInvokeEvents(bool immediate_only) ...@@ -1397,7 +1414,6 @@ deferredTriggerInvokeEvents(bool immediate_only)
List *el; List *el;
DeferredTriggerEvent event; DeferredTriggerEvent event;
int still_deferred_ones; int still_deferred_ones;
int eventno = -1;
int i; int i;
MemoryContext per_tuple_context; MemoryContext per_tuple_context;
...@@ -1421,8 +1437,6 @@ deferredTriggerInvokeEvents(bool immediate_only) ...@@ -1421,8 +1437,6 @@ deferredTriggerInvokeEvents(bool immediate_only)
foreach(el, deftrig_events) foreach(el, deftrig_events)
{ {
eventno++;
MemoryContextReset(per_tuple_context); MemoryContextReset(per_tuple_context);
/* ---------- /* ----------
...@@ -1548,6 +1562,7 @@ DeferredTriggerBeginXact(void) ...@@ -1548,6 +1562,7 @@ DeferredTriggerBeginXact(void)
deftrig_n_events = 0; deftrig_n_events = 0;
deftrig_events = NIL; deftrig_events = NIL;
deftrig_event_tail = NIL;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment