Changes improve the performance of INSERT and UPDATE

Started by Hiroki Kataokaover 20 years ago2 messages
#1Hiroki Kataoka
kataoka@interwiz.jp
1 attachment(s)

Hi all,

This small patch improves the performance of INSERT and UPDATE. By my
machine, these changes raised the performance about 5%~10% in pgbench.
Please take a benchmark in a reliable environment. Since I may forget
some required changes, I specify that this patch is experimental. But
note that all regression tests have passed.

Thanks,

--
Hiroki Kataoka <kataoka@interwiz.jp>

Attachments:

pageadditem.patchtext/plain; name=pageadditem.patchDownload
diff -ru postgresql-cvs.orig/src/backend/storage/page/bufpage.c postgresql-cvs/src/backend/storage/page/bufpage.c
--- postgresql-cvs.orig/src/backend/storage/page/bufpage.c	2005-06-15 16:53:00.000000000 +0900
+++ postgresql-cvs/src/backend/storage/page/bufpage.c	2005-07-14 07:41:11.000000000 +0900
@@ -42,6 +42,7 @@
 	p->pd_lower = SizeOfPageHeaderData;
 	p->pd_upper = pageSize - specialSize;
 	p->pd_special = pageSize - specialSize;
+	p->pd_insoff = FirstOffsetNumber;
 	PageSetPageSizeAndVersion(page, pageSize, PG_PAGE_LAYOUT_VERSION);
 }
 
@@ -100,7 +101,7 @@
  *	If offsetNumber is valid and <= current max offset in the page,
  *	insert item into the array at that position by shuffling ItemId's
  *	down to make room.
- *	If offsetNumber is not valid, then assign one by finding the first
+ *	If offsetNumber is not valid, then assign one by finding the next
  *	one that is both unused and deallocated.
  *
  *	!!! EREPORT(ERROR) IS DISALLOWED HERE !!!
@@ -120,6 +121,7 @@
 	OffsetNumber limit;
 	bool		needshuffle = false;
 	bool		overwritemode = (flags & OverwritePageMode) != 0;
+	bool		findunusedlinp = false;
 
 	flags &= ~OverwritePageMode;
 
@@ -165,9 +167,15 @@
 	}
 	else
 	{
-		/* offsetNumber was not passed in, so find a free slot */
-		/* look for "recyclable" (unused & deallocated) ItemId */
-		for (offsetNumber = 1; offsetNumber < limit; offsetNumber++)
+		/* offsetNumber was not passed in, try to use pd_insoff */
+		if (OffsetNumberIsValid(phdr->pd_insoff))
+			offsetNumber = phdr->pd_insoff;
+		else
+			offsetNumber = FirstOffsetNumber;
+
+		/* so find a free slot look for "recyclable" (unused & deallocated) */
+		/* ItemId */
+		for (; offsetNumber < limit; offsetNumber++)
 		{
 			itemId = PageGetItemId(phdr, offsetNumber);
 			if (((itemId->lp_flags & LP_USED) == 0) &&
@@ -175,6 +183,8 @@
 				break;
 		}
 		/* if no free slot, we'll put it at limit (1st open slot) */
+
+		findunusedlinp = true;
 	}
 
 	if (offsetNumber > limit)
@@ -222,6 +232,8 @@
 	/* adjust page header */
 	phdr->pd_lower = (LocationIndex) lower;
 	phdr->pd_upper = (LocationIndex) upper;
+	if (findunusedlinp)
+		phdr->pd_insoff = OffsetNumberNext(offsetNumber);
 
 	return offsetNumber;
 }
@@ -345,8 +357,13 @@
 			lp->lp_flags &= ~(LP_USED | LP_DELETE);
 		if (lp->lp_flags & LP_USED)
 			nused++;
-		else if (unused)
-			unused[i - nused] = (OffsetNumber) i;
+		else
+		{
+			if (i - nused == 0)	/* check if it's first unused line pointer */
+				((PageHeader) page)->pd_insoff = (OffsetNumber) i + 1;
+			if (unused)
+				unused[i - nused] = (OffsetNumber) i;
+		}
 	}
 
 	if (nused == 0)
diff -ru postgresql-cvs.orig/src/include/storage/bufpage.h postgresql-cvs/src/include/storage/bufpage.h
--- postgresql-cvs.orig/src/include/storage/bufpage.h	2005-04-29 06:47:18.000000000 +0900
+++ postgresql-cvs/src/include/storage/bufpage.h	2005-07-14 06:57:03.000000000 +0900
@@ -125,6 +125,7 @@
 	LocationIndex pd_lower;		/* offset to start of free space */
 	LocationIndex pd_upper;		/* offset to end of free space */
 	LocationIndex pd_special;	/* offset to start of special space */
+	OffsetNumber pd_insoff;		/* offset number for next new item */
 	uint16		pd_pagesize_version;
 	ItemIdData	pd_linp[1];		/* beginning of line pointer array */
 } PageHeaderData;
#2Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Hiroki Kataoka (#1)
Re: Changes improve the performance of INSERT and UPDATE

This has been saved for the 8.2 release:

http://momjian.postgresql.org/cgi-bin/pgpatches_hold

---------------------------------------------------------------------------

Hiroki Kataoka wrote:

Hi all,

This small patch improves the performance of INSERT and UPDATE. By my
machine, these changes raised the performance about 5%~10% in pgbench.
Please take a benchmark in a reliable environment. Since I may forget
some required changes, I specify that this patch is experimental. But
note that all regression tests have passed.

Thanks,

--
Hiroki Kataoka <kataoka@interwiz.jp>

diff -ru postgresql-cvs.orig/src/backend/storage/page/bufpage.c postgresql-cvs/src/backend/storage/page/bufpage.c
--- postgresql-cvs.orig/src/backend/storage/page/bufpage.c	2005-06-15 16:53:00.000000000 +0900
+++ postgresql-cvs/src/backend/storage/page/bufpage.c	2005-07-14 07:41:11.000000000 +0900
@@ -42,6 +42,7 @@
p->pd_lower = SizeOfPageHeaderData;
p->pd_upper = pageSize - specialSize;
p->pd_special = pageSize - specialSize;
+	p->pd_insoff = FirstOffsetNumber;
PageSetPageSizeAndVersion(page, pageSize, PG_PAGE_LAYOUT_VERSION);
}
@@ -100,7 +101,7 @@
*	If offsetNumber is valid and <= current max offset in the page,
*	insert item into the array at that position by shuffling ItemId's
*	down to make room.
- *	If offsetNumber is not valid, then assign one by finding the first
+ *	If offsetNumber is not valid, then assign one by finding the next
*	one that is both unused and deallocated.
*
*	!!! EREPORT(ERROR) IS DISALLOWED HERE !!!
@@ -120,6 +121,7 @@
OffsetNumber limit;
bool		needshuffle = false;
bool		overwritemode = (flags & OverwritePageMode) != 0;
+	bool		findunusedlinp = false;

flags &= ~OverwritePageMode;

@@ -165,9 +167,15 @@
}
else
{
-		/* offsetNumber was not passed in, so find a free slot */
-		/* look for "recyclable" (unused & deallocated) ItemId */
-		for (offsetNumber = 1; offsetNumber < limit; offsetNumber++)
+		/* offsetNumber was not passed in, try to use pd_insoff */
+		if (OffsetNumberIsValid(phdr->pd_insoff))
+			offsetNumber = phdr->pd_insoff;
+		else
+			offsetNumber = FirstOffsetNumber;
+
+		/* so find a free slot look for "recyclable" (unused & deallocated) */
+		/* ItemId */
+		for (; offsetNumber < limit; offsetNumber++)
{
itemId = PageGetItemId(phdr, offsetNumber);
if (((itemId->lp_flags & LP_USED) == 0) &&
@@ -175,6 +183,8 @@
break;
}
/* if no free slot, we'll put it at limit (1st open slot) */
+
+		findunusedlinp = true;
}
if (offsetNumber > limit)
@@ -222,6 +232,8 @@
/* adjust page header */
phdr->pd_lower = (LocationIndex) lower;
phdr->pd_upper = (LocationIndex) upper;
+	if (findunusedlinp)
+		phdr->pd_insoff = OffsetNumberNext(offsetNumber);
return offsetNumber;
}
@@ -345,8 +357,13 @@
lp->lp_flags &= ~(LP_USED | LP_DELETE);
if (lp->lp_flags & LP_USED)
nused++;
-		else if (unused)
-			unused[i - nused] = (OffsetNumber) i;
+		else
+		{
+			if (i - nused == 0)	/* check if it's first unused line pointer */
+				((PageHeader) page)->pd_insoff = (OffsetNumber) i + 1;
+			if (unused)
+				unused[i - nused] = (OffsetNumber) i;
+		}
}
if (nused == 0)
diff -ru postgresql-cvs.orig/src/include/storage/bufpage.h postgresql-cvs/src/include/storage/bufpage.h
--- postgresql-cvs.orig/src/include/storage/bufpage.h	2005-04-29 06:47:18.000000000 +0900
+++ postgresql-cvs/src/include/storage/bufpage.h	2005-07-14 06:57:03.000000000 +0900
@@ -125,6 +125,7 @@
LocationIndex pd_lower;		/* offset to start of free space */
LocationIndex pd_upper;		/* offset to end of free space */
LocationIndex pd_special;	/* offset to start of special space */
+	OffsetNumber pd_insoff;		/* offset number for next new item */
uint16		pd_pagesize_version;
ItemIdData	pd_linp[1];		/* beginning of line pointer array */
} PageHeaderData;

---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073