v1-0001-Limit-batch_size-for-foreign-insert-with-work_mem.patch
text/x-diff
Filename: v1-0001-Limit-batch_size-for-foreign-insert-with-work_mem.patch
Type: text/x-diff
Part: 0
From 7bb6aeadd318ede7f78b98908d58a432bee3309f Mon Sep 17 00:00:00 2001
From: Alexander Pyhalov <a.pyhalov@postgrespro.ru>
Date: Tue, 16 Dec 2025 18:46:27 +0300
Subject: [PATCH 1/2] Limit batch_size for foreign insert with work_mem
Option batch_size can be set on foreign server level. It can be very optimistic
even for one table with different tuple lengths. To prevent large memory usage
limit effective batch size with work_mem.
---
src/backend/executor/nodeModifyTable.c | 38 ++++++++++++++++++++++++--
1 file changed, 35 insertions(+), 3 deletions(-)
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 874b71e6608..19cedde0faa 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -176,6 +176,8 @@ static TupleTableSlot *ExecMergeNotMatched(ModifyTableContext *context,
ResultRelInfo *resultRelInfo,
bool canSetTag);
+static Size estimate_batch_length(ResultRelInfo *resultRelInfo);
+
/*
* Verify that the tuples to be produced by INSERT match the
@@ -828,6 +830,33 @@ ExecGetUpdateNewTuple(ResultRelInfo *relinfo,
return ExecProject(newProj);
}
+/*
+ * estimate_batch_length
+ * When batch foreign insert is enabled, estimate size of
+ * currently gathered batch.
+ */
+static Size
+estimate_batch_length(ResultRelInfo *resultRelInfo)
+{
+ Size batch_len = 0;
+ int i = 0;
+
+ for (i = 0; i < resultRelInfo->ri_NumSlots; i++)
+ {
+ TupleTableSlot *slot;
+ Size slot_tuple_len;
+
+ slot = resultRelInfo->ri_Slots[i];
+
+ slot_getallattrs(slot);
+ slot_tuple_len = heap_compute_data_size(slot->tts_tupleDescriptor, slot->tts_values, slot->tts_isnull);
+ batch_len += slot_tuple_len;
+ }
+
+ return batch_len;
+}
+
+
/* ----------------------------------------------------------------
* ExecInsert
*
@@ -943,12 +972,15 @@ ExecInsert(ModifyTableContext *context,
if (resultRelInfo->ri_BatchSize > 1)
{
bool flushed = false;
+ Size batch_len;
+
+ batch_len = estimate_batch_length(resultRelInfo);
/*
- * When we've reached the desired batch size, perform the
- * insertion.
+ * When we've reached the desired batch size or exceeded work_mem,
+ * perform the insertion.
*/
- if (resultRelInfo->ri_NumSlots == resultRelInfo->ri_BatchSize)
+ if (resultRelInfo->ri_NumSlots == resultRelInfo->ri_BatchSize || batch_len > work_mem)
{
ExecBatchInsert(mtstate, resultRelInfo,
resultRelInfo->ri_Slots,
--
2.43.0