diff --git a/src/backend/access/common/relation.c b/src/backend/access/common/relation.c
index d8a313a2c9..74b1415ad5 100644
--- a/src/backend/access/common/relation.c
+++ b/src/backend/access/common/relation.c
@@ -70,7 +70,10 @@ relation_open(Oid relationId, LOCKMODE lockmode)
 
 	/* Make note that we've accessed a temporary relation */
 	if (RelationUsesLocalBuffers(r))
+	{
 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
+		on_commits_filter_add(relationId);
+	}
 
 	pgstat_init_relation(r);
 
@@ -120,7 +123,10 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
 
 	/* Make note that we've accessed a temporary relation */
 	if (RelationUsesLocalBuffers(r))
+	{
 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
+		on_commits_filter_add(relationId);
+	}
 
 	pgstat_init_relation(r);
 
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index d119ab909d..dc7bde98ab 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -2122,6 +2122,9 @@ StartTransaction(void)
 	forceSyncCommit = false;
 	MyXactFlags = 0;
 
+	/* When starting a new transaction, init or reset the oncommit filter. */
+	on_commits_filter_init_or_reset();
+
 	/*
 	 * reinitialize within-transaction counters
 	 */
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index cd20ae76ba..77ad85576d 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -98,7 +98,10 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid,
 	 */
 	relpersistence = get_rel_persistence(relid);
 	if (relpersistence == RELPERSISTENCE_TEMP)
+	{
 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
+		on_commits_filter_add(relid);
+	}
 
 	/* Check permissions. */
 	aclresult = LockTableAclCheck(relid, lockmode, GetUserId());
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index dbfe0d6b1c..e3695cee16 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -68,6 +68,7 @@
 #include "executor/executor.h"
 #include "foreign/fdwapi.h"
 #include "foreign/foreign.h"
+#include "lib/bloomfilter.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
@@ -128,6 +129,15 @@ typedef struct OnCommitItem
 
 static List *on_commits = NIL;
 
+/*
+ * Filter out the temporary tables accessed in the current transaction.
+ * The number of bits for the bloom filter is fixed at 1KB, which provides a
+ * good false positive rate even with 1000 items.
+ */
+#define	ON_COMMITS_FILTER_K_HASH_FUNCS 2
+#define ON_COMMITS_FILTER_THRESHOLD 2
+#define ON_COMMITS_FILTER_KB 1
+static bloom_filter* on_commits_filter = NULL;
 
 /*
  * State information for ALTER TABLE
@@ -662,6 +672,7 @@ static void ATExecSplitPartition(List **wqueue, AlteredTableInfo *tab,
 								 AlterTableUtilityContext *context);
 static void ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel,
 								  PartitionCmd *cmd, AlterTableUtilityContext *context);
+static bool on_commits_filter_contains(Oid relid);
 
 /* ----------------------------------------------------------------
  *		DefineRelation
@@ -17429,7 +17440,23 @@ PreCommit_on_commit_actions(void)
 				 * tables, as they must still be empty.
 				 */
 				if ((MyXactFlags & XACT_FLAGS_ACCESSEDTEMPNAMESPACE))
-					oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
+				{
+					if (on_commits_filter_contains(oc->relid))
+						oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
+#ifdef USE_ASSERT_CHECKING
+					else
+					{
+						/*
+						 * All temporary tables not in the filter should either
+						 * have no physical files or a file size of zero.
+						 */
+						Relation rel;
+						rel = table_open(oc->relid, AccessShareLock);
+						Assert(!rel->rd_smgr || !smgrexists(rel->rd_smgr, MAIN_FORKNUM) || smgrnblocks(rel->rd_smgr, MAIN_FORKNUM) == 0);
+						table_close(rel, AccessShareLock);
+					}
+#endif
+				}
 				break;
 			case ONCOMMIT_DROP:
 				oids_to_drop = lappend_oid(oids_to_drop, oc->relid);
@@ -20766,3 +20793,65 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	/* Keep the lock until commit. */
 	table_close(newPartRel, NoLock);
 }
+
+/*
+ * on_commits_filter_init_or_reset: Initialize or reset the bloom filter,
+ * ensuring it is only initialized when the number of on_commits exceeds the
+ * ON_COMMITS_FILTER_THRESHOLD. It is called when starting a new transaction,
+ * that is, when the XACT_FLAGS_ACCESSEDTEMPNAMESPACE flag is cleared.
+ */
+void
+on_commits_filter_init_or_reset(void)
+{
+	if (list_length(on_commits) < ON_COMMITS_FILTER_THRESHOLD)
+	{
+		if (on_commits_filter != NULL)
+		{
+			bloom_free(on_commits_filter);
+			on_commits_filter = NULL;
+		}
+		return;
+	}
+	if (on_commits_filter != NULL)
+		bloom_clear(on_commits_filter);
+	else
+	{
+		MemoryContext oldcxt;
+
+		oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
+		on_commits_filter =
+			bloom_create_v2(ON_COMMITS_FILTER_K_HASH_FUNCS, ON_COMMITS_FILTER_KB, 0);
+		MemoryContextSwitchTo(oldcxt);
+	}
+}
+
+/*
+ * on_commits_filter_add: Add the temporary table OId to the Bloom filter,
+ * indicating that the current transaction has accessed this temporary table,
+ * which needs to be truncated upon commit. It is called when the temporary
+ * table is opened.
+ */
+void
+on_commits_filter_add(Oid relid)
+{
+	if (on_commits_filter != NULL)
+		bloom_add_element(on_commits_filter, (unsigned char *) &relid, sizeof(relid));
+}
+
+/*
+ * on_commits_filter_contains: Determine whether the specified temporary table
+ * has been accessed in the current transaction.
+ */
+static bool
+on_commits_filter_contains(Oid relid)
+{
+	/*
+	 * If the on_commits filter is not initialized, assuming that the current
+	 * transaction has accessed the temp table defaultly, keeping the logic
+	 * consistent with when there is no filter.
+	 */
+	if (on_commits_filter == NULL)
+		return true;
+
+	return !bloom_lacks_element(on_commits_filter, (unsigned char *) &relid, sizeof(relid));
+}
diff --git a/src/backend/lib/bloomfilter.c b/src/backend/lib/bloomfilter.c
index 360d21ca45..c33ffd1d3c 100644
--- a/src/backend/lib/bloomfilter.c
+++ b/src/backend/lib/bloomfilter.c
@@ -119,6 +119,42 @@ bloom_create(int64 total_elems, int bloom_work_mem, uint64 seed)
 	return filter;
 }
 
+/*
+ * Create  Bloom filter with a specified memory size and specified number of
+ * hash functions in the caller's memory context.
+ * bloom_work_mem is sized in KB, in line with the general work_mem convention.
+ * This determines the size of the underlying bitset (trivial bookkeeping space
+ * isn't counted).
+ */
+bloom_filter *
+bloom_create_v2(int64 k_hash_funcs, int bloom_work_mem, uint64 seed)
+{
+	bloom_filter *filter;
+	int			bloom_power;
+	uint64		bitset_bytes;
+	uint64		bitset_bits;
+
+	Assert(bloom_work_mem > 0);
+	bitset_bytes = bloom_work_mem * UINT64CONST(1024);
+
+	/*
+	 * Size in bits should be the highest power of two <= target.  bitset_bits
+	 * is uint64 because PG_UINT32_MAX is 2^32 - 1, not 2^32
+	 */
+	bloom_power = my_bloom_power(bitset_bytes * BITS_PER_BYTE);
+	bitset_bits = UINT64CONST(1) << bloom_power;
+	bitset_bytes = bitset_bits / BITS_PER_BYTE;
+
+	/* Allocate bloom filter with unset bitset */
+	filter = palloc0(offsetof(bloom_filter, bitset) +
+					 sizeof(unsigned char) * bitset_bytes);
+	filter->k_hash_funcs = k_hash_funcs;
+	filter->seed = seed;
+	filter->m = bitset_bits;
+
+	return filter;
+}
+
 /*
  * Free Bloom filter
  */
@@ -292,3 +328,8 @@ mod_m(uint32 val, uint64 m)
 
 	return val & (m - 1);
 }
+
+void bloom_clear(bloom_filter *filter)
+{
+	memset(filter->bitset, 0, filter->m / BITS_PER_BYTE);
+}
\ No newline at end of file
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index 85cbad3d0c..461bc1ea47 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -107,4 +107,7 @@ extern void RangeVarCallbackOwnsRelation(const RangeVar *relation,
 extern bool PartConstraintImpliedByRelConstraint(Relation scanrel,
 												 List *partConstraint);
 
+extern void on_commits_filter_init_or_reset(void);
+extern void on_commits_filter_add(Oid relid);
+
 #endif							/* TABLECMDS_H */
diff --git a/src/include/lib/bloomfilter.h b/src/include/lib/bloomfilter.h
index 6ec7173843..11b0ab1264 100644
--- a/src/include/lib/bloomfilter.h
+++ b/src/include/lib/bloomfilter.h
@@ -17,11 +17,14 @@ typedef struct bloom_filter bloom_filter;
 
 extern bloom_filter *bloom_create(int64 total_elems, int bloom_work_mem,
 								  uint64 seed);
+extern bloom_filter *bloom_create_v2(int64 k_hash_funcs, int bloom_work_mem,
+									 uint64 seed);
 extern void bloom_free(bloom_filter *filter);
 extern void bloom_add_element(bloom_filter *filter, unsigned char *elem,
 							  size_t len);
 extern bool bloom_lacks_element(bloom_filter *filter, unsigned char *elem,
 								size_t len);
 extern double bloom_prop_bits_set(bloom_filter *filter);
+extern void bloom_clear(bloom_filter *filter);
 
 #endif							/* BLOOMFILTER_H */
