aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeModifyTable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeModifyTable.c')
-rw-r--r--src/backend/executor/nodeModifyTable.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 379b0563105..88c479c6da3 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -703,16 +703,31 @@ ExecInsert(ModifyTableState *mtstate,
resultRelInfo->ri_BatchSize);
}
- resultRelInfo->ri_Slots[resultRelInfo->ri_NumSlots] =
- MakeSingleTupleTableSlot(slot->tts_tupleDescriptor,
- slot->tts_ops);
- ExecCopySlot(resultRelInfo->ri_Slots[resultRelInfo->ri_NumSlots],
- slot);
- resultRelInfo->ri_PlanSlots[resultRelInfo->ri_NumSlots] =
- MakeSingleTupleTableSlot(planSlot->tts_tupleDescriptor,
- planSlot->tts_ops);
- ExecCopySlot(resultRelInfo->ri_PlanSlots[resultRelInfo->ri_NumSlots],
- planSlot);
+ /*
+ * Initialize the batch slots. We don't know how many slots will be
+ * needed, so we initialize them as the batch grows, and we keep
+ * them across batches. To mitigate an inefficiency in how resource
+ * owner handles objects with many references (as with many slots
+ * all referencing the same tuple descriptor) we copy the tuple
+ * descriptor for each slot.
+ */
+ if (resultRelInfo->ri_NumSlots >= resultRelInfo->ri_NumSlotsInitialized)
+ {
+ TupleDesc tdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
+
+ resultRelInfo->ri_Slots[resultRelInfo->ri_NumSlots] =
+ MakeSingleTupleTableSlot(tdesc, slot->tts_ops);
+ ExecCopySlot(resultRelInfo->ri_Slots[resultRelInfo->ri_NumSlots],
+ slot);
+
+ resultRelInfo->ri_PlanSlots[resultRelInfo->ri_NumSlots] =
+ MakeSingleTupleTableSlot(tdesc, planSlot->tts_ops);
+ ExecCopySlot(resultRelInfo->ri_PlanSlots[resultRelInfo->ri_NumSlots],
+ planSlot);
+
+ /* remember how many batch slots we initialized */
+ resultRelInfo->ri_NumSlotsInitialized++;
+ }
resultRelInfo->ri_NumSlots++;
@@ -1034,12 +1049,6 @@ ExecBatchInsert(ModifyTableState *mtstate,
if (canSetTag && numInserted > 0)
estate->es_processed += numInserted;
-
- for (i = 0; i < numSlots; i++)
- {
- ExecDropSingleTupleTableSlot(slots[i]);
- ExecDropSingleTupleTableSlot(planSlots[i]);
- }
}
/* ----------------------------------------------------------------
@@ -3162,6 +3171,7 @@ ExecEndModifyTable(ModifyTableState *node)
*/
for (i = 0; i < node->mt_nrels; i++)
{
+ int j;
ResultRelInfo *resultRelInfo = node->resultRelInfo + i;
if (!resultRelInfo->ri_usesFdwDirectModify &&
@@ -3169,6 +3179,16 @@ ExecEndModifyTable(ModifyTableState *node)
resultRelInfo->ri_FdwRoutine->EndForeignModify != NULL)
resultRelInfo->ri_FdwRoutine->EndForeignModify(node->ps.state,
resultRelInfo);
+
+ /*
+ * Cleanup the initialized batch slots. This only matters for FDWs with
+ * batching, but the other cases will have ri_NumSlotsInitialized == 0.
+ */
+ for (j = 0; j < resultRelInfo->ri_NumSlotsInitialized; j++)
+ {
+ ExecDropSingleTupleTableSlot(resultRelInfo->ri_Slots[j]);
+ ExecDropSingleTupleTableSlot(resultRelInfo->ri_PlanSlots[j]);
+ }
}
/*