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

Commitc5b7ba4

Browse files
committed
Postpone some stuff out of ExecInitModifyTable.
Arrange to do some things on-demand, rather than immediately duringexecutor startup, because there's a fair chance of never having to dothem at all:* Don't open result relations' indexes until needed.* Don't initialize partition tuple routing, nor the child-to-roottuple conversion map, until needed.This wins in UPDATEs on partitioned tables when only some of thepartitions will actually receive updates; with larger partitioncounts the savings is quite noticeable. Also, we can remove somesketchy heuristics in ExecInitModifyTable about whether to set uptuple routing.Also, remove execPartition.c's private hash table tracking whichpartitions were already opened by the ModifyTable node. Insteaduse the hash added to ModifyTable itself by commit86dc900.To allow lazy computation of the conversion maps, we now setri_RootResultRelInfo in all child ResultRelInfos. We formerly set itonly in some, not terribly well-defined, cases. This has user-visibleside effects in that now more error messages refer to the rootrelation instead of some partition (and provide error data in theroot's column order, too). It looks to me like this is a strictimprovement in consistency, so I don't have a problem with theoutput changes visible in this commit.Extracted from a larger patch, which seemed to me to be too messyto push in one commit.Amit Langote, reviewed at different times by Heikki Linnakangas andmyselfDiscussion:https://postgr.es/m/CA+HiwqG7ZruBmmih3wPsBZ4s0H2EhywrnXEduckY5Hr3fWzPWA@mail.gmail.com
1 parenta3740c4 commitc5b7ba4

File tree

13 files changed

+235
-267
lines changed

13 files changed

+235
-267
lines changed

‎src/backend/commands/copyfrom.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ CopyFrom(CopyFromState cstate)
697697
* CopyFrom tuple routing.
698698
*/
699699
if (cstate->rel->rd_rel->relkind==RELKIND_PARTITIONED_TABLE)
700-
proute=ExecSetupPartitionTupleRouting(estate,NULL,cstate->rel);
700+
proute=ExecSetupPartitionTupleRouting(estate,cstate->rel);
701701

702702
if (cstate->whereClause)
703703
cstate->qualexpr=ExecInitQual(castNode(List,cstate->whereClause),

‎src/backend/commands/trigger.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5479,7 +5479,7 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
54795479
if (row_trigger&&transition_capture!=NULL)
54805480
{
54815481
TupleTableSlot*original_insert_tuple=transition_capture->tcs_original_insert_tuple;
5482-
TupleConversionMap*map=relinfo->ri_ChildToRootMap;
5482+
TupleConversionMap*map=ExecGetChildToRootMap(relinfo);
54835483
booldelete_old_table=transition_capture->tcs_delete_old_table;
54845484
boolupdate_old_table=transition_capture->tcs_update_old_table;
54855485
boolupdate_new_table=transition_capture->tcs_update_new_table;

‎src/backend/executor/execMain.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,11 +1231,19 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
12311231
resultRelInfo->ri_ReturningSlot=NULL;
12321232
resultRelInfo->ri_TrigOldSlot=NULL;
12331233
resultRelInfo->ri_TrigNewSlot=NULL;
1234+
1235+
/*
1236+
* Only ExecInitPartitionInfo() and ExecInitPartitionDispatchInfo() pass
1237+
* non-NULL partition_root_rri. For child relations that are part of the
1238+
* initial query rather than being dynamically added by tuple routing,
1239+
* this field is filled in ExecInitModifyTable().
1240+
*/
12341241
resultRelInfo->ri_RootResultRelInfo=partition_root_rri;
12351242
resultRelInfo->ri_RootToPartitionMap=NULL;/* set by
12361243
* ExecInitRoutingInfo */
12371244
resultRelInfo->ri_PartitionTupleSlot=NULL;/* ditto */
12381245
resultRelInfo->ri_ChildToRootMap=NULL;
1246+
resultRelInfo->ri_ChildToRootMapValid= false;
12391247
resultRelInfo->ri_CopyMultiInsertBuffer=NULL;
12401248
}
12411249

‎src/backend/executor/execPartition.c

Lines changed: 48 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,17 @@
6666
*
6767
* partitions
6868
*Array of 'max_partitions' elements containing a pointer to a
69-
*ResultRelInfo for every leafpartitions touched by tuple routing.
69+
*ResultRelInfo for every leafpartition touched by tuple routing.
7070
*Some of these are pointers to ResultRelInfos which are borrowed out of
71-
*'subplan_resultrel_htab'. The remainder have been built especially
72-
*for tuple routing. See comment for PartitionDispatchData->indexes for
73-
*details on how this array is indexed.
71+
*the owning ModifyTableState node. The remainder have been built
72+
*especially for tuple routing. See comment for
73+
*PartitionDispatchData->indexes for details on how this array is
74+
*indexed.
75+
*
76+
* is_borrowed_rel
77+
*Array of 'max_partitions' booleans recording whether a given entry
78+
*in 'partitions' is a ResultRelInfo pointer borrowed from the owning
79+
*ModifyTableState node, rather than being built here.
7480
*
7581
* num_partitions
7682
*The current number of items stored in the 'partitions' array. Also
@@ -80,12 +86,6 @@
8086
* max_partitions
8187
*The current allocated size of the 'partitions' array.
8288
*
83-
* subplan_resultrel_htab
84-
*Hash table to store subplan ResultRelInfos by Oid. This is used to
85-
*cache ResultRelInfos from targets of an UPDATE ModifyTable node;
86-
*NULL in other cases. Some of these may be useful for tuple routing
87-
*to save having to build duplicates.
88-
*
8989
* memcxt
9090
*Memory context used to allocate subsidiary structs.
9191
*-----------------------
@@ -98,9 +98,9 @@ struct PartitionTupleRouting
9898
intnum_dispatch;
9999
intmax_dispatch;
100100
ResultRelInfo**partitions;
101+
bool*is_borrowed_rel;
101102
intnum_partitions;
102103
intmax_partitions;
103-
HTAB*subplan_resultrel_htab;
104104
MemoryContextmemcxt;
105105
};
106106

@@ -153,16 +153,7 @@ typedef struct PartitionDispatchData
153153
intindexes[FLEXIBLE_ARRAY_MEMBER];
154154
}PartitionDispatchData;
155155

156-
/* struct to hold result relations coming from UPDATE subplans */
157-
typedefstructSubplanResultRelHashElem
158-
{
159-
Oidrelid;/* hash key -- must be first */
160-
ResultRelInfo*rri;
161-
}SubplanResultRelHashElem;
162-
163156

164-
staticvoidExecHashSubPlanResultRelsByOid(ModifyTableState*mtstate,
165-
PartitionTupleRouting*proute);
166157
staticResultRelInfo*ExecInitPartitionInfo(ModifyTableState*mtstate,
167158
EState*estate,PartitionTupleRouting*proute,
168159
PartitionDispatchdispatch,
@@ -173,7 +164,8 @@ static void ExecInitRoutingInfo(ModifyTableState *mtstate,
173164
PartitionTupleRouting*proute,
174165
PartitionDispatchdispatch,
175166
ResultRelInfo*partRelInfo,
176-
intpartidx);
167+
intpartidx,
168+
boolis_borrowed_rel);
177169
staticPartitionDispatchExecInitPartitionDispatchInfo(EState*estate,
178170
PartitionTupleRouting*proute,
179171
Oidpartoid,PartitionDispatchparent_pd,
@@ -215,11 +207,9 @@ static void find_matching_subplans_recurse(PartitionPruningData *prunedata,
215207
* it should be estate->es_query_cxt.
216208
*/
217209
PartitionTupleRouting*
218-
ExecSetupPartitionTupleRouting(EState*estate,ModifyTableState*mtstate,
219-
Relationrel)
210+
ExecSetupPartitionTupleRouting(EState*estate,Relationrel)
220211
{
221212
PartitionTupleRouting*proute;
222-
ModifyTable*node=mtstate ? (ModifyTable*)mtstate->ps.plan :NULL;
223213

224214
/*
225215
* Here we attempt to expend as little effort as possible in setting up
@@ -241,17 +231,6 @@ ExecSetupPartitionTupleRouting(EState *estate, ModifyTableState *mtstate,
241231
ExecInitPartitionDispatchInfo(estate,proute,RelationGetRelid(rel),
242232
NULL,0,NULL);
243233

244-
/*
245-
* If performing an UPDATE with tuple routing, we can reuse partition
246-
* sub-plan result rels. We build a hash table to map the OIDs of
247-
* partitions present in mtstate->resultRelInfo to their ResultRelInfos.
248-
* Every time a tuple is routed to a partition that we've yet to set the
249-
* ResultRelInfo for, before we go to the trouble of making one, we check
250-
* for a pre-made one in the hash table.
251-
*/
252-
if (node&&node->operation==CMD_UPDATE)
253-
ExecHashSubPlanResultRelsByOid(mtstate,proute);
254-
255234
returnproute;
256235
}
257236

@@ -351,7 +330,6 @@ ExecFindPartition(ModifyTableState *mtstate,
351330
is_leaf=partdesc->is_leaf[partidx];
352331
if (is_leaf)
353332
{
354-
355333
/*
356334
* We've reached the leaf -- hurray, we're done. Look to see if
357335
* we've already got a ResultRelInfo for this partition.
@@ -364,42 +342,33 @@ ExecFindPartition(ModifyTableState *mtstate,
364342
}
365343
else
366344
{
367-
boolfound= false;
368-
369345
/*
370-
*We have not yet set up a ResultRelInfo for this partition,
371-
*but ifwehave a subplan hash table, we might have one
372-
*there. If not, we'll have to create one.
346+
*If the partition is known in the owning ModifyTableState
347+
*node,wecan re-use that ResultRelInfo instead of creating
348+
*a new one with ExecInitPartitionInfo().
373349
*/
374-
if (proute->subplan_resultrel_htab)
350+
rri=ExecLookupResultRelByOid(mtstate,
351+
partdesc->oids[partidx],
352+
true, false);
353+
if (rri)
375354
{
376-
Oidpartoid=partdesc->oids[partidx];
377-
SubplanResultRelHashElem*elem;
355+
/* Verify this ResultRelInfo allows INSERTs */
356+
CheckValidResultRel(rri,CMD_INSERT);
378357

379-
elem=hash_search(proute->subplan_resultrel_htab,
380-
&partoid,HASH_FIND,NULL);
381-
if (elem)
382-
{
383-
found= true;
384-
rri=elem->rri;
385-
386-
/* Verify this ResultRelInfo allows INSERTs */
387-
CheckValidResultRel(rri,CMD_INSERT);
388-
389-
/*
390-
* Initialize information needed to insert this and
391-
* subsequent tuples routed to this partition.
392-
*/
393-
ExecInitRoutingInfo(mtstate,estate,proute,dispatch,
394-
rri,partidx);
395-
}
358+
/*
359+
* Initialize information needed to insert this and
360+
* subsequent tuples routed to this partition.
361+
*/
362+
ExecInitRoutingInfo(mtstate,estate,proute,dispatch,
363+
rri,partidx, true);
396364
}
397-
398-
/* We need to create a new one. */
399-
if (!found)
365+
else
366+
{
367+
/* We need to create a new one. */
400368
rri=ExecInitPartitionInfo(mtstate,estate,proute,
401369
dispatch,
402370
rootResultRelInfo,partidx);
371+
}
403372
}
404373
Assert(rri!=NULL);
405374

@@ -509,50 +478,6 @@ ExecFindPartition(ModifyTableState *mtstate,
509478
returnrri;
510479
}
511480

512-
/*
513-
* ExecHashSubPlanResultRelsByOid
514-
*Build a hash table to allow fast lookups of subplan ResultRelInfos by
515-
*partition Oid. We also populate the subplan ResultRelInfo with an
516-
*ri_PartitionRoot.
517-
*/
518-
staticvoid
519-
ExecHashSubPlanResultRelsByOid(ModifyTableState*mtstate,
520-
PartitionTupleRouting*proute)
521-
{
522-
HASHCTLctl;
523-
HTAB*htab;
524-
inti;
525-
526-
ctl.keysize=sizeof(Oid);
527-
ctl.entrysize=sizeof(SubplanResultRelHashElem);
528-
ctl.hcxt=CurrentMemoryContext;
529-
530-
htab=hash_create("PartitionTupleRouting table",mtstate->mt_nrels,
531-
&ctl,HASH_ELEM |HASH_BLOBS |HASH_CONTEXT);
532-
proute->subplan_resultrel_htab=htab;
533-
534-
/* Hash all subplans by their Oid */
535-
for (i=0;i<mtstate->mt_nrels;i++)
536-
{
537-
ResultRelInfo*rri=&mtstate->resultRelInfo[i];
538-
boolfound;
539-
Oidpartoid=RelationGetRelid(rri->ri_RelationDesc);
540-
SubplanResultRelHashElem*elem;
541-
542-
elem= (SubplanResultRelHashElem*)
543-
hash_search(htab,&partoid,HASH_ENTER,&found);
544-
Assert(!found);
545-
elem->rri=rri;
546-
547-
/*
548-
* This is required in order to convert the partition's tuple to be
549-
* compatible with the root partitioned table's tuple descriptor. When
550-
* generating the per-subplan result rels, this was not set.
551-
*/
552-
rri->ri_RootResultRelInfo=mtstate->rootResultRelInfo;
553-
}
554-
}
555-
556481
/*
557482
* ExecInitPartitionInfo
558483
*Lock the partition and initialize ResultRelInfo. Also setup other
@@ -613,7 +538,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
613538
* didn't build the withCheckOptionList for partitions within the planner,
614539
* but simple translation of varattnos will suffice. This only occurs for
615540
* the INSERT case or in the case of UPDATE tuple routing where we didn't
616-
* find a result rel to reuse in ExecSetupPartitionTupleRouting().
541+
* find a result rel to reuse.
617542
*/
618543
if (node&&node->withCheckOptionLists!=NIL)
619544
{
@@ -676,7 +601,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
676601
* build the returningList for partitions within the planner, but simple
677602
* translation of varattnos will suffice. This only occurs for the INSERT
678603
* case or in the case of UPDATE tuple routing where we didn't find a
679-
* result rel to reuse in ExecSetupPartitionTupleRouting().
604+
* result rel to reuse.
680605
*/
681606
if (node&&node->returningLists!=NIL)
682607
{
@@ -734,7 +659,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
734659

735660
/* Set up information needed for routing tuples to the partition. */
736661
ExecInitRoutingInfo(mtstate,estate,proute,dispatch,
737-
leaf_part_rri,partidx);
662+
leaf_part_rri,partidx, false);
738663

739664
/*
740665
* If there is an ON CONFLICT clause, initialize state for it.
@@ -910,15 +835,6 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
910835
}
911836
}
912837

913-
/*
914-
* Also, if transition capture is required, store a map to convert tuples
915-
* from partition's rowtype to the root partition table's.
916-
*/
917-
if (mtstate->mt_transition_capture||mtstate->mt_oc_transition_capture)
918-
leaf_part_rri->ri_ChildToRootMap=
919-
convert_tuples_by_name(RelationGetDescr(leaf_part_rri->ri_RelationDesc),
920-
RelationGetDescr(rootResultRelInfo->ri_RelationDesc));
921-
922838
/*
923839
* Since we've just initialized this ResultRelInfo, it's not in any list
924840
* attached to the estate as yet. Add it, so that it can be found later.
@@ -949,7 +865,8 @@ ExecInitRoutingInfo(ModifyTableState *mtstate,
949865
PartitionTupleRouting*proute,
950866
PartitionDispatchdispatch,
951867
ResultRelInfo*partRelInfo,
952-
intpartidx)
868+
intpartidx,
869+
boolis_borrowed_rel)
953870
{
954871
ResultRelInfo*rootRelInfo=partRelInfo->ri_RootResultRelInfo;
955872
MemoryContextoldcxt;
@@ -1029,17 +946,23 @@ ExecInitRoutingInfo(ModifyTableState *mtstate,
1029946
proute->max_partitions=8;
1030947
proute->partitions= (ResultRelInfo**)
1031948
palloc(sizeof(ResultRelInfo*)*proute->max_partitions);
949+
proute->is_borrowed_rel= (bool*)
950+
palloc(sizeof(bool)*proute->max_partitions);
1032951
}
1033952
else
1034953
{
1035954
proute->max_partitions *=2;
1036955
proute->partitions= (ResultRelInfo**)
1037956
repalloc(proute->partitions,sizeof(ResultRelInfo*)*
1038957
proute->max_partitions);
958+
proute->is_borrowed_rel= (bool*)
959+
repalloc(proute->is_borrowed_rel,sizeof(bool)*
960+
proute->max_partitions);
1039961
}
1040962
}
1041963

1042964
proute->partitions[rri_index]=partRelInfo;
965+
proute->is_borrowed_rel[rri_index]=is_borrowed_rel;
1043966
dispatch->indexes[partidx]=rri_index;
1044967

1045968
MemoryContextSwitchTo(oldcxt);
@@ -1199,7 +1122,6 @@ void
11991122
ExecCleanupTupleRouting(ModifyTableState*mtstate,
12001123
PartitionTupleRouting*proute)
12011124
{
1202-
HTAB*htab=proute->subplan_resultrel_htab;
12031125
inti;
12041126

12051127
/*
@@ -1230,20 +1152,11 @@ ExecCleanupTupleRouting(ModifyTableState *mtstate,
12301152
resultRelInfo);
12311153

12321154
/*
1233-
*Checkifthis result rel is one belonging to the node's subplans,
1234-
*if so, let ExecEndPlan() clean it up.
1155+
*Close itifit's not one of the result relations borrowed from the
1156+
*owning ModifyTableState; those will be closed by ExecEndPlan().
12351157
*/
1236-
if (htab)
1237-
{
1238-
Oidpartoid;
1239-
boolfound;
1240-
1241-
partoid=RelationGetRelid(resultRelInfo->ri_RelationDesc);
1242-
1243-
(void)hash_search(htab,&partoid,HASH_FIND,&found);
1244-
if (found)
1245-
continue;
1246-
}
1158+
if (proute->is_borrowed_rel[i])
1159+
continue;
12471160

12481161
ExecCloseIndices(resultRelInfo);
12491162
table_close(resultRelInfo->ri_RelationDesc,NoLock);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp