Hi,

Based on the investigation and (lack of) progress so far, I'll revert
part of the COPY FREEZE improvements shortly. I'll keep the initial
7db0cd2145 changes, tweaking heap_multi_insert, and remove most of
39b66a91bd (except for the heap_xlog_multi_insert bit).

This should address the small 5% regression in refresh matview. I have
no other ideas how to fix that, short of adding a user-level option to
REFRESH MATERIALIZED VIEW command so that the users can opt out/in.

Attached is the revert patch - I'll get it committed in the next day or
two, once the tests complete (running with CCA so it takes time).

regards

On 5/25/21 12:30 AM, Tomas Vondra wrote:
> On 5/24/21 8:21 PM, Andres Freund wrote:
>> Hi,
>>
>> On 2021-05-24 12:37:18 +0200, Tomas Vondra wrote:
>>> Another option might be changes in the binary layout - 5% change is well
>>> within the range that could be attributed to this, but it feels very
>>> hand-wavy and more like an excuse than real analysis.
>>
>> I don't think 5% is likely to be explained by binary layout unless you
>> look for an explicitly adverse layout.
>>
> 
> Yeah, true. But I'm out of ideas what might be causing the regression
> and how to fix it :-(
> 
>>
>>> Hmmm, thanks for reminding us that patch. Why did we reject that approach in
>>> favor of the current one?
>>
>> Don't know about others, but I think it's way too fragile.
>>
> 
> Is it really that fragile? Any particular risks you have in mind? Maybe
> we could protect against that somehow ... Anyway, that change would
> certainly be for PG15.
> 
> 
> regards
> 

-- 
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index bd60129aeb..2433998f39 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -2063,12 +2063,8 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 	TransactionId xid = GetCurrentTransactionId();
 	HeapTuple	heaptup;
 	Buffer		buffer;
-	Page		page = NULL;
 	Buffer		vmbuffer = InvalidBuffer;
-	bool		starting_with_empty_page;
 	bool		all_visible_cleared = false;
-	bool		all_frozen_set = false;
-	uint8		vmstatus = 0;
 
 	/* Cheap, simplistic check that the tuple matches the rel's rowtype. */
 	Assert(HeapTupleHeaderGetNatts(tup->t_data) <=
@@ -2085,36 +2081,11 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 	/*
 	 * Find buffer to insert this tuple into.  If the page is all visible,
 	 * this will also pin the requisite visibility map page.
-	 *
-	 * Also pin visibility map page if COPY FREEZE inserts tuples into an
-	 * empty page. See all_frozen_set below.
 	 */
 	buffer = RelationGetBufferForTuple(relation, heaptup->t_len,
 									   InvalidBuffer, options, bistate,
 									   &vmbuffer, NULL);
 
-
-	/*
-	 * If we're inserting frozen entry into an empty page, set visibility map
-	 * bits and PageAllVisible() hint.
-	 *
-	 * If we're inserting frozen entry into already all_frozen page, preserve
-	 * this state.
-	 */
-	if (options & HEAP_INSERT_FROZEN)
-	{
-		page = BufferGetPage(buffer);
-
-		starting_with_empty_page = PageGetMaxOffsetNumber(page) == 0;
-
-		if (visibilitymap_pin_ok(BufferGetBlockNumber(buffer), vmbuffer))
-			vmstatus = visibilitymap_get_status(relation,
-												BufferGetBlockNumber(buffer), &vmbuffer);
-
-		if ((starting_with_empty_page || vmstatus & VISIBILITYMAP_ALL_FROZEN))
-			all_frozen_set = true;
-	}
-
 	/*
 	 * We're about to do the actual insert -- but check for conflict first, to
 	 * avoid possibly having to roll back work we've just done.
@@ -2138,14 +2109,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 	RelationPutHeapTuple(relation, buffer, heaptup,
 						 (options & HEAP_INSERT_SPECULATIVE) != 0);
 
-	/*
-	 * If the page is all visible, need to clear that, unless we're only going
-	 * to add further frozen rows to it.
-	 *
-	 * If we're only adding already frozen rows to a page that was empty or
-	 * marked as all visible, mark it as all-visible.
-	 */
-	if (PageIsAllVisible(BufferGetPage(buffer)) && !(options & HEAP_INSERT_FROZEN))
+	if (PageIsAllVisible(BufferGetPage(buffer)))
 	{
 		all_visible_cleared = true;
 		PageClearAllVisible(BufferGetPage(buffer));
@@ -2153,13 +2117,6 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 							ItemPointerGetBlockNumber(&(heaptup->t_self)),
 							vmbuffer, VISIBILITYMAP_VALID_BITS);
 	}
-	else if (all_frozen_set)
-	{
-		/* We only ever set all_frozen_set after reading the page. */
-		Assert(page);
-
-		PageSetAllVisible(page);
-	}
 
 	/*
 	 * XXX Should we set PageSetPrunable on this page ?
@@ -2207,8 +2164,6 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 		xlrec.flags = 0;
 		if (all_visible_cleared)
 			xlrec.flags |= XLH_INSERT_ALL_VISIBLE_CLEARED;
-		if (all_frozen_set)
-			xlrec.flags = XLH_INSERT_ALL_FROZEN_SET;
 		if (options & HEAP_INSERT_SPECULATIVE)
 			xlrec.flags |= XLH_INSERT_IS_SPECULATIVE;
 		Assert(ItemPointerGetBlockNumber(&heaptup->t_self) == BufferGetBlockNumber(buffer));
@@ -2257,29 +2212,6 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 
 	END_CRIT_SECTION();
 
-	/*
-	 * If we've frozen everything on the page, update the visibilitymap. We're
-	 * already holding pin on the vmbuffer.
-	 *
-	 * No need to update the visibilitymap if it had all_frozen bit set before
-	 * this insertion.
-	 */
-	if (all_frozen_set && ((vmstatus & VISIBILITYMAP_ALL_FROZEN) == 0))
-	{
-		Assert(PageIsAllVisible(page));
-		Assert(visibilitymap_pin_ok(BufferGetBlockNumber(buffer), vmbuffer));
-
-		/*
-		 * It's fine to use InvalidTransactionId here - this is only used when
-		 * HEAP_INSERT_FROZEN is specified, which intentionally violates
-		 * visibility rules.
-		 */
-		visibilitymap_set(relation, BufferGetBlockNumber(buffer), buffer,
-						  InvalidXLogRecPtr, vmbuffer,
-						  InvalidTransactionId,
-						  VISIBILITYMAP_ALL_VISIBLE | VISIBILITYMAP_ALL_FROZEN);
-	}
-
 	UnlockReleaseBuffer(buffer);
 	if (vmbuffer != InvalidBuffer)
 		ReleaseBuffer(vmbuffer);
@@ -8946,10 +8878,6 @@ heap_xlog_insert(XLogReaderState *record)
 	ItemPointerSetBlockNumber(&target_tid, blkno);
 	ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum);
 
-	/* check that the mutually exclusive flags are not both set */
-	Assert(!((xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) &&
-			 (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET)));
-
 	/*
 	 * The visibility map may need to be fixed even if the heap page is
 	 * already up-to-date.
diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index d34edb4190..4097a7aa18 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -406,20 +406,20 @@ RelationGetBufferForTuple(Relation relation, Size len,
 		 * We have no cached target page, so ask the FSM for an initial
 		 * target.
 		 */
-		targetBlock = GetPageWithFreeSpace(relation, targetFreeSpace);
-	}
+		targetBlock = GetPageWithFreeSpace(relation, len + saveFreeSpace);
 
-	/*
-	 * If the FSM knows nothing of the rel, try the last page before we give
-	 * up and extend.  This avoids one-tuple-per-page syndrome during
-	 * bootstrapping or in a recently-started system.
-	 */
-	if (targetBlock == InvalidBlockNumber)
-	{
-		BlockNumber nblocks = RelationGetNumberOfBlocks(relation);
+		/*
+		 * If the FSM knows nothing of the rel, try the last page before we
+		 * give up and extend.  This avoids one-tuple-per-page syndrome during
+		 * bootstrapping or in a recently-started system.
+		 */
+		if (targetBlock == InvalidBlockNumber)
+		{
+			BlockNumber nblocks = RelationGetNumberOfBlocks(relation);
 
-		if (nblocks > 0)
-			targetBlock = nblocks - 1;
+			if (nblocks > 0)
+				targetBlock = nblocks - 1;
+		}
 	}
 
 loop:

Reply via email to