>
> Yea, that anlysis sounds right. Peter?
>
Thanks Andres for the confirmation on my initial analysis. I'm not
sure why Peter hasn't commented on it so far. However, I continued
investigating on it further and here are findings

I think, the root cause of this problem is that CopyFrom() is using
the stale value of *has_before_insert_row_trig* to determine if the
current partition is okay for multi-insert or not i.e.
has_before_insert_row_trig used to determine multi-insert condition
for the current partition actually belongs to old partition. I think,
*has_before_insert_row_trig* needs to updated before CopyFrom()
evaluates if the current partition is good to go for multi insert or
not. Attached is the patch based on this. I've also added the relevant
test-case for it. Peter, David, Could you please have a look into the
attached patch and share your thoughts. Thank you.

-- 
With Regards,
Ashutosh Sharma
EnterpriseDB:http://www.enterprisedb.com
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 86b0fb3..ac21ff2 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2784,17 +2784,6 @@ CopyFrom(CopyState cstate)
 						nPartitionChanges = 0;
 					}
 
-					/*
-					 * Tests have shown that using multi-inserts when the
-					 * partition changes on every tuple slightly decreases the
-					 * performance, however, there are benefits even when only
-					 * some batches have just 2 tuples, so let's enable
-					 * multi-inserts even when the average is quite low.
-					 */
-					leafpart_use_multi_insert = avgTuplesPerPartChange >= 1.3 &&
-						!has_before_insert_row_trig &&
-						!has_instead_insert_row_trig &&
-						resultRelInfo->ri_FdwRoutine == NULL;
 				}
 				else
 					leafpart_use_multi_insert = false;
@@ -2820,6 +2809,18 @@ CopyFrom(CopyState cstate)
 
 				has_instead_insert_row_trig = (resultRelInfo->ri_TrigDesc &&
 											   resultRelInfo->ri_TrigDesc->trig_insert_instead_row);
+				/*
+				 * Tests have shown that using multi-inserts when the
+				 * partition changes on every tuple slightly decreases the
+				 * performance, however, there are benefits even when only
+				 * some batches have just 2 tuples, so let's enable
+				 * multi-inserts even when the average is quite low.
+				 */
+				if (insertMethod == CIM_MULTI_CONDITIONAL)
+					leafpart_use_multi_insert = avgTuplesPerPartChange >= 1.3 &&
+						!has_before_insert_row_trig &&
+						!has_instead_insert_row_trig &&
+						resultRelInfo->ri_FdwRoutine == NULL;
 
 				/*
 				 * We'd better make the bulk insert mechanism gets a new
diff --git a/src/test/regress/input/copy.source b/src/test/regress/input/copy.source
index 014b1b5..4cb03c5 100644
--- a/src/test/regress/input/copy.source
+++ b/src/test/regress/input/copy.source
@@ -162,4 +162,23 @@ copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv';
 select tableoid::regclass,count(*),sum(a) from parted_copytest
 group by tableoid order by tableoid::regclass::name;
 
+truncate parted_copytest;
+
+-- create before insert row trigger on parted_copytest_a2
+create function part_ins_func() returns trigger language plpgsql as $$
+begin
+  return new;
+end;
+$$;
+
+create trigger part_ins_trig
+	before insert on parted_copytest_a2
+	for each row
+	execute procedure part_ins_func();
+
+copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv';
+
+select tableoid::regclass,count(*),sum(a) from parted_copytest
+group by tableoid order by tableoid::regclass::name;
+
 drop table parted_copytest;
diff --git a/src/test/regress/output/copy.source b/src/test/regress/output/copy.source
index ab09615..ddd652c 100644
--- a/src/test/regress/output/copy.source
+++ b/src/test/regress/output/copy.source
@@ -121,4 +121,24 @@ group by tableoid order by tableoid::regclass::name;
  parted_copytest_a2 |    10 |  10055
 (2 rows)
 
+truncate parted_copytest;
+-- create before insert row trigger on parted_copytest_a2
+create function part_ins_func() returns trigger language plpgsql as $$
+begin
+  return new;
+end;
+$$;
+create trigger part_ins_trig
+	before insert on parted_copytest_a2
+	for each row
+	execute procedure part_ins_func();
+copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv';
+select tableoid::regclass,count(*),sum(a) from parted_copytest
+group by tableoid order by tableoid::regclass::name;
+      tableoid      | count |  sum   
+--------------------+-------+--------
+ parted_copytest_a1 |  1010 | 510655
+ parted_copytest_a2 |    10 |  10055
+(2 rows)
+
 drop table parted_copytest;

Reply via email to