On Thu, 2010-04-22 at 20:39 +0200, Erik Rijkers wrote:
> On Sun, April 18, 2010 13:01, Simon Riggs wrote:
> any comment is welcome...
Please can you re-run with -l and post me the file of times
Please also rebuild using --enable-profile so we can see what's
happening.
Can you also try the enclosed patch which implements prefetching during
replay of btree delete records. (Need to set effective_io_concurrency)
Thanks for your further help.
--
Simon Riggs www.2ndQuadrant.com
diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c
index f4c7bf4..9918688 100644
--- a/src/backend/access/nbtree/nbtxlog.c
+++ b/src/backend/access/nbtree/nbtxlog.c
@@ -578,6 +578,8 @@ btree_xlog_delete_get_latestRemovedXid(XLogRecord *record)
OffsetNumber hoffnum;
TransactionId latestRemovedXid = InvalidTransactionId;
TransactionId htupxid = InvalidTransactionId;
+ TransactionId oldestxmin = GetCurrentOldestXmin(true, true);
+ TransactionId latestCompletedXid;
int i;
/*
@@ -586,8 +588,12 @@ btree_xlog_delete_get_latestRemovedXid(XLogRecord *record)
* That returns InvalidTransactionId, and so will conflict with
* users, but since we just worked out that's zero people, its OK.
*/
- if (CountDBBackends(InvalidOid) == 0)
- return latestRemovedXid;
+ if (!TransactionIdIsValid(oldestxmin))
+ return oldestxmin;
+
+ LWLockAcquire(ProcArrayLock, LW_SHARED);
+ latestCompletedXid = ShmemVariableCache->latestCompletedXid;
+ LWLockRelease(ProcArrayLock);
/*
* Get index page
@@ -603,6 +609,27 @@ btree_xlog_delete_get_latestRemovedXid(XLogRecord *record)
*/
unused = (OffsetNumber *) ((char *) xlrec + SizeOfBtreeDelete);
+ /*
+ * Prefetch the heap buffers.
+ */
+ for (i = 0; i < xlrec->nitems; i++)
+ {
+ /*
+ * Identify the index tuple about to be deleted
+ */
+ iitemid = PageGetItemId(ipage, unused[i]);
+ itup = (IndexTuple) PageGetItem(ipage, iitemid);
+
+ /*
+ * Locate the heap page that the index tuple points at
+ */
+ hblkno = ItemPointerGetBlockNumber(&(itup->t_tid));
+ XLogPrefetchBuffer(xlrec->hnode, MAIN_FORKNUM, hblkno);
+ }
+
+ /*
+ * Read through the heap tids
+ */
for (i = 0; i < xlrec->nitems; i++)
{
/*
@@ -659,6 +686,16 @@ btree_xlog_delete_get_latestRemovedXid(XLogRecord *record)
latestRemovedXid = htupxid;
htupxid = HeapTupleHeaderGetXmax(htuphdr);
+
+ /*
+ * Stop searching when we've found a recent xid
+ */
+ if (TransactionIdFollowsOrEquals(htupxid,latestCompletedXid))
+ {
+ UnlockReleaseBuffer(hbuffer);
+ break;
+ }
+
if (TransactionIdFollows(htupxid, latestRemovedXid))
latestRemovedXid = htupxid;
}
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 9ee2036..3ea3a40 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -342,6 +342,16 @@ XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum,
return buffer;
}
+void
+XLogPrefetchBuffer(RelFileNode rnode, ForkNumber forknum,
+ BlockNumber blkno)
+{
+ Relation reln = CreateFakeRelcacheEntry(rnode);
+
+ reln->rd_istemp = false;
+
+ PrefetchBuffer(reln, forknum, blkno);
+}
/*
* Struct actually returned by XLogFakeRelcacheEntry, though the declared
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 5a214c8..bb23c16 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -933,6 +933,21 @@ TransactionIdIsActive(TransactionId xid)
TransactionId
GetOldestXmin(bool allDbs, bool ignoreVacuum)
{
+ TransactionId result = GetCurrentOldestXmin(allDbs, ignoreVacuum);
+
+ /*
+ * Compute the cutoff XID, being careful not to generate a "permanent" XID
+ */
+ result -= vacuum_defer_cleanup_age;
+ if (!TransactionIdIsNormal(result))
+ result = FirstNormalTransactionId;
+
+ return result;
+}
+
+TransactionId
+GetCurrentOldestXmin(bool allDbs, bool ignoreVacuum)
+{
ProcArrayStruct *arrayP = procArray;
TransactionId result;
int index;
@@ -985,13 +1000,6 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum)
LWLockRelease(ProcArrayLock);
- /*
- * Compute the cutoff XID, being careful not to generate a "permanent" XID
- */
- result -= vacuum_defer_cleanup_age;
- if (!TransactionIdIsNormal(result))
- result = FirstNormalTransactionId;
-
return result;
}
diff --git a/src/include/access/xlogutils.h b/src/include/access/xlogutils.h
index 8477f88..caa8aa3 100644
--- a/src/include/access/xlogutils.h
+++ b/src/include/access/xlogutils.h
@@ -28,6 +28,9 @@ extern void XLogTruncateRelation(RelFileNode rnode, ForkNumber forkNum,
extern Buffer XLogReadBuffer(RelFileNode rnode, BlockNumber blkno, bool init);
extern Buffer XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum,
BlockNumber blkno, ReadBufferMode mode);
+extern void XLogPrefetchBuffer(RelFileNode rnode, ForkNumber forknum,
+ BlockNumber blkno);
+
extern Relation CreateFakeRelcacheEntry(RelFileNode rnode);
extern void FreeFakeRelcacheEntry(Relation fakerel);
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index 5a026e9..24fee59 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -46,6 +46,7 @@ extern Snapshot GetSnapshotData(Snapshot snapshot);
extern bool TransactionIdIsInProgress(TransactionId xid);
extern bool TransactionIdIsActive(TransactionId xid);
extern TransactionId GetOldestXmin(bool allDbs, bool ignoreVacuum);
+extern TransactionId GetCurrentOldestXmin(bool allDbs, bool ignoreVacuum);
extern int GetTransactionsInCommit(TransactionId **xids_p);
extern bool HaveTransactionsInCommit(TransactionId *xids, int nxids);
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers