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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers