Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit817946b

Browse files
committed
Arrange to cache a ResultRelInfo in the executor's EState for relations that
are not one of the query's defined result relations, but nonetheless havetriggers fired against them while the query is active. This was formerlyimpossible but can now occur because of my recent patch to fix the firingorder for RI triggers. Caching a ResultRelInfo avoids duplicating work byrepeatedly opening and closing the same relation, and also allows EXPLAINANALYZE to "see" and report on these extra triggers. Use the same mechanismto cache open relations when firing deferred triggers at transaction shutdown;this replaces the former one-element-cache strategy used in that case, andshould improve performance a bit when there are deferred triggers on a numberof relations.
1 parent9cb8409 commit817946b

File tree

6 files changed

+223
-139
lines changed

6 files changed

+223
-139
lines changed

‎src/backend/commands/explain.c

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.164 2007/05/25 17:54:24 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.165 2007/08/15 21:39:50 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -52,6 +52,8 @@ typedef struct ExplainState
5252
staticvoidExplainOneQuery(Query*query,ExplainStmt*stmt,
5353
constchar*queryString,
5454
ParamListInfoparams,TupOutputState*tstate);
55+
staticvoidreport_triggers(ResultRelInfo*rInfo,boolshow_relname,
56+
StringInfobuf);
5557
staticdoubleelapsed_time(instr_time*starttime);
5658
staticvoidexplain_outNode(StringInfostr,
5759
Plan*plan,PlanState*planstate,
@@ -310,50 +312,21 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
310312
if (es->printAnalyze)
311313
{
312314
ResultRelInfo*rInfo;
315+
boolshow_relname;
313316
intnumrels=queryDesc->estate->es_num_result_relations;
317+
List*targrels=queryDesc->estate->es_trig_target_relations;
314318
intnr;
319+
ListCell*l;
315320

321+
show_relname= (numrels>1||targrels!=NIL);
316322
rInfo=queryDesc->estate->es_result_relations;
317323
for (nr=0;nr<numrels;rInfo++,nr++)
318-
{
319-
intnt;
320-
321-
if (!rInfo->ri_TrigDesc|| !rInfo->ri_TrigInstrument)
322-
continue;
323-
for (nt=0;nt<rInfo->ri_TrigDesc->numtriggers;nt++)
324-
{
325-
Trigger*trig=rInfo->ri_TrigDesc->triggers+nt;
326-
Instrumentation*instr=rInfo->ri_TrigInstrument+nt;
327-
char*conname;
324+
report_triggers(rInfo,show_relname,&buf);
328325

329-
/* Must clean up instrumentation state */
330-
InstrEndLoop(instr);
331-
332-
/*
333-
* We ignore triggers that were never invoked; they likely
334-
* aren't relevant to the current query type.
335-
*/
336-
if (instr->ntuples==0)
337-
continue;
338-
339-
if (OidIsValid(trig->tgconstraint)&&
340-
(conname=get_constraint_name(trig->tgconstraint))!=NULL)
341-
{
342-
appendStringInfo(&buf,"Trigger for constraint %s",
343-
conname);
344-
pfree(conname);
345-
}
346-
else
347-
appendStringInfo(&buf,"Trigger %s",trig->tgname);
348-
349-
if (numrels>1)
350-
appendStringInfo(&buf," on %s",
351-
RelationGetRelationName(rInfo->ri_RelationDesc));
352-
353-
appendStringInfo(&buf,": time=%.3f calls=%.0f\n",
354-
1000.0*instr->total,
355-
instr->ntuples);
356-
}
326+
foreach(l,targrels)
327+
{
328+
rInfo= (ResultRelInfo*)lfirst(l);
329+
report_triggers(rInfo,show_relname,&buf);
357330
}
358331
}
359332

@@ -382,6 +355,51 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
382355
pfree(es);
383356
}
384357

358+
/*
359+
* report_triggers -
360+
*report execution stats for a single relation's triggers
361+
*/
362+
staticvoid
363+
report_triggers(ResultRelInfo*rInfo,boolshow_relname,StringInfobuf)
364+
{
365+
intnt;
366+
367+
if (!rInfo->ri_TrigDesc|| !rInfo->ri_TrigInstrument)
368+
return;
369+
for (nt=0;nt<rInfo->ri_TrigDesc->numtriggers;nt++)
370+
{
371+
Trigger*trig=rInfo->ri_TrigDesc->triggers+nt;
372+
Instrumentation*instr=rInfo->ri_TrigInstrument+nt;
373+
char*conname;
374+
375+
/* Must clean up instrumentation state */
376+
InstrEndLoop(instr);
377+
378+
/*
379+
* We ignore triggers that were never invoked; they likely
380+
* aren't relevant to the current query type.
381+
*/
382+
if (instr->ntuples==0)
383+
continue;
384+
385+
if (OidIsValid(trig->tgconstraint)&&
386+
(conname=get_constraint_name(trig->tgconstraint))!=NULL)
387+
{
388+
appendStringInfo(buf,"Trigger for constraint %s",conname);
389+
pfree(conname);
390+
}
391+
else
392+
appendStringInfo(buf,"Trigger %s",trig->tgname);
393+
394+
if (show_relname)
395+
appendStringInfo(buf," on %s",
396+
RelationGetRelationName(rInfo->ri_RelationDesc));
397+
398+
appendStringInfo(buf,": time=%.3f calls=%.0f\n",
399+
1000.0*instr->total,instr->ntuples);
400+
}
401+
}
402+
385403
/* Compute elapsed time in seconds since given timestamp */
386404
staticdouble
387405
elapsed_time(instr_time*starttime)

‎src/backend/commands/trigger.c

Lines changed: 39 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.217 2007/08/1519:15:46 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.218 2007/08/1521:39:50 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -2313,11 +2313,10 @@ afterTriggerMarkEvents(AfterTriggerEventList *events,
23132313
*Scan the given event list for events that are marked as to be fired
23142314
*in the current firing cycle, and fire them.
23152315
*
2316-
*If estate isn't NULL, then we expect that all the firable events are
2317-
*for triggers of the relations included in the estate's result relation
2318-
*array.This allows us to re-use the estate's open relations and
2319-
*trigger cache info. When estate is NULL, we have to find the relations
2320-
*the hard way.
2316+
*If estate isn't NULL, we use its result relation info to avoid repeated
2317+
*openings and closing of trigger target relations. If it is NULL, we
2318+
*make one locally to cache the info in case there are multiple trigger
2319+
*events per rel.
23212320
*
23222321
*When delete_ok is TRUE, it's okay to delete fully-processed events.
23232322
*The events list pointers are updated.
@@ -2332,12 +2331,19 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
23322331
AfterTriggerEventevent,
23332332
prev_event;
23342333
MemoryContextper_tuple_context;
2335-
boollocally_opened= false;
2334+
boollocal_estate= false;
23362335
Relationrel=NULL;
23372336
TriggerDesc*trigdesc=NULL;
23382337
FmgrInfo*finfo=NULL;
23392338
Instrumentation*instr=NULL;
23402339

2340+
/* Make a local EState if need be */
2341+
if (estate==NULL)
2342+
{
2343+
estate=CreateExecutorState();
2344+
local_estate= true;
2345+
}
2346+
23412347
/* Make a per-tuple memory context for trigger function calls */
23422348
per_tuple_context=
23432349
AllocSetContextCreate(CurrentMemoryContext,
@@ -2360,77 +2366,21 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
23602366
event->ate_firing_id==firing_id)
23612367
{
23622368
/*
2363-
* So let's fire it... but first,open the correct relation if
2369+
* So let's fire it... but first,find the correct relation if
23642370
* this is not the same relation as before.
23652371
*/
2366-
if (rel==NULL||rel->rd_id!=event->ate_relid)
2372+
if (rel==NULL||RelationGetRelid(rel)!=event->ate_relid)
23672373
{
2368-
if (locally_opened)
2369-
{
2370-
/* close prior rel if any */
2371-
if (rel)
2372-
heap_close(rel,NoLock);
2373-
if (trigdesc)
2374-
FreeTriggerDesc(trigdesc);
2375-
if (finfo)
2376-
pfree(finfo);
2377-
Assert(instr==NULL);/* never used in this case */
2378-
}
2379-
locally_opened= true;
2380-
2381-
if (estate)
2382-
{
2383-
/* Find target relation among estate's result rels */
2384-
ResultRelInfo*rInfo;
2385-
intnr;
2386-
2387-
rInfo=estate->es_result_relations;
2388-
nr=estate->es_num_result_relations;
2389-
while (nr>0)
2390-
{
2391-
if (rInfo->ri_RelationDesc->rd_id==event->ate_relid)
2392-
{
2393-
rel=rInfo->ri_RelationDesc;
2394-
trigdesc=rInfo->ri_TrigDesc;
2395-
finfo=rInfo->ri_TrigFunctions;
2396-
instr=rInfo->ri_TrigInstrument;
2397-
locally_opened= false;
2398-
break;
2399-
}
2400-
rInfo++;
2401-
nr--;
2402-
}
2403-
}
2404-
2405-
if (locally_opened)
2406-
{
2407-
/* Hard way: open target relation for ourselves */
2408-
2409-
/*
2410-
* We assume that an appropriate lock is still held by the
2411-
* executor, so grab no new lock here.
2412-
*/
2413-
rel=heap_open(event->ate_relid,NoLock);
2414-
2415-
/*
2416-
* Copy relation's trigger info so that we have a stable
2417-
* copy no matter what the called triggers do.
2418-
*/
2419-
trigdesc=CopyTriggerDesc(rel->trigdesc);
2420-
2421-
if (trigdesc==NULL)/* should not happen */
2422-
elog(ERROR,"relation %u has no triggers",
2423-
event->ate_relid);
2424-
2425-
/*
2426-
* Allocate space to cache fmgr lookup info for triggers.
2427-
*/
2428-
finfo= (FmgrInfo*)
2429-
palloc0(trigdesc->numtriggers*sizeof(FmgrInfo));
2430-
2431-
/* Never any EXPLAIN info in this case */
2432-
instr=NULL;
2433-
}
2374+
ResultRelInfo*rInfo;
2375+
2376+
rInfo=ExecGetTriggerResultRel(estate,event->ate_relid);
2377+
rel=rInfo->ri_RelationDesc;
2378+
trigdesc=rInfo->ri_TrigDesc;
2379+
finfo=rInfo->ri_TrigFunctions;
2380+
instr=rInfo->ri_TrigInstrument;
2381+
if (trigdesc==NULL)/* should not happen */
2382+
elog(ERROR,"relation %u has no triggers",
2383+
event->ate_relid);
24342384
}
24352385

24362386
/*
@@ -2480,17 +2430,22 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
24802430
events->tail=prev_event;
24812431

24822432
/* Release working resources */
2483-
if (locally_opened)
2433+
MemoryContextDelete(per_tuple_context);
2434+
2435+
if (local_estate)
24842436
{
2485-
if (rel)
2486-
heap_close(rel,NoLock);
2487-
if (trigdesc)
2488-
FreeTriggerDesc(trigdesc);
2489-
if (finfo)
2490-
pfree(finfo);
2491-
Assert(instr==NULL);/* never used in this case */
2437+
ListCell*l;
2438+
2439+
foreach(l,estate->es_trig_target_relations)
2440+
{
2441+
ResultRelInfo*resultRelInfo= (ResultRelInfo*)lfirst(l);
2442+
2443+
/* Close indices and then the relation itself */
2444+
ExecCloseIndices(resultRelInfo);
2445+
heap_close(resultRelInfo->ri_RelationDesc,NoLock);
2446+
}
2447+
FreeExecutorState(estate);
24922448
}
2493-
MemoryContextDelete(per_tuple_context);
24942449
}
24952450

24962451

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp