*** tqual--unchanged.c 2012-09-20 03:17:58.000000000 +0530 --- tqual.c 2012-11-14 23:27:30.470499857 +0530 *************** *** 75,80 **** --- 75,88 ---- /* local functions */ static bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); + /* + * Single-item cache for results of clog visibility check. It's worth having + * such a cache to help reduce the amount of hint bit traffic when + * many sequentially touched tuples have the same XID. + */ + static TransactionId cachedVisibilityXid; + /* Visibility status cache stores the commit status of the XID in cachedVisibilityXid */ + static uint16 cachedVisibilityXidStatus; /* * SetHintBits() *************** *** 117,122 **** --- 125,133 ---- if (XLogNeedsFlush(commitLSN) && BufferIsPermanent(buffer)) return; /* not flushed yet, so don't set hint */ + + cachedVisibilityXid = xid; + cachedVisibilityXidStatus = infomask; } tuple->t_infomask |= infomask; *************** *** 164,170 **** bool HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; --- 175,183 ---- bool HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED) ! && !(cachedVisibilityXid == HeapTupleHeaderGetXmin(tuple) ! && cachedVisibilityXidStatus == HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; *************** *** 247,253 **** if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; ! if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; --- 260,268 ---- if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; ! if ((tuple->t_infomask & HEAP_XMAX_COMMITTED) ! || (cachedVisibilityXid == HeapTupleHeaderGetXmax(tuple) ! && cachedVisibilityXidStatus == HEAP_XMAX_COMMITTED)) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; *************** *** 327,333 **** bool HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; --- 342,350 ---- bool HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED) ! && !(cachedVisibilityXid == HeapTupleHeaderGetXmin(tuple) ! && cachedVisibilityXidStatus == HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; *************** *** 416,422 **** if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; ! if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; --- 433,441 ---- if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; ! if ((tuple->t_infomask & HEAP_XMAX_COMMITTED) ! || (cachedVisibilityXid == HeapTupleHeaderGetXmax(tuple) ! && cachedVisibilityXidStatus == HEAP_XMAX_COMMITTED)) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; *************** *** 493,499 **** HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; --- 512,520 ---- HeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED) ! && !(cachedVisibilityXid == HeapTupleHeaderGetXmin(tuple) ! && cachedVisibilityXidStatus == HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; *************** *** 574,580 **** HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return HeapTupleInvisible; --- 595,603 ---- HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED) ! && !(cachedVisibilityXid == HeapTupleHeaderGetXmin(tuple) ! && cachedVisibilityXidStatus == HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return HeapTupleInvisible; *************** *** 663,669 **** if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return HeapTupleMayBeUpdated; ! if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return HeapTupleMayBeUpdated; --- 686,694 ---- if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return HeapTupleMayBeUpdated; ! if ((tuple->t_infomask & HEAP_XMAX_COMMITTED) ! || (cachedVisibilityXid == HeapTupleHeaderGetXmax(tuple) ! && cachedVisibilityXidStatus == HEAP_XMAX_COMMITTED)) { if (tuple->t_infomask & HEAP_IS_LOCKED) return HeapTupleMayBeUpdated; *************** *** 743,749 **** { snapshot->xmin = snapshot->xmax = InvalidTransactionId; ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; --- 768,776 ---- { snapshot->xmin = snapshot->xmax = InvalidTransactionId; ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED) ! && !(cachedVisibilityXid == HeapTupleHeaderGetXmin(tuple) ! && cachedVisibilityXidStatus == HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; *************** *** 830,836 **** if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; ! if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; --- 857,865 ---- if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true; ! if ((tuple->t_infomask & HEAP_XMAX_COMMITTED) ! || (cachedVisibilityXid == HeapTupleHeaderGetXmax(tuple) ! && cachedVisibilityXidStatus == HEAP_XMAX_COMMITTED)) { if (tuple->t_infomask & HEAP_IS_LOCKED) return true; *************** *** 904,910 **** HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; --- 933,941 ---- HeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) { ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED) ! && !(cachedVisibilityXid == HeapTupleHeaderGetXmin(tuple) ! && cachedVisibilityXidStatus == HEAP_XMIN_COMMITTED)) { if (tuple->t_infomask & HEAP_XMIN_INVALID) return false; *************** *** 1008,1014 **** return true; } ! if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) { if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) { --- 1039,1047 ---- return true; } ! if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED) ! && !(cachedVisibilityXid == HeapTupleHeaderGetXmax(tuple) ! && cachedVisibilityXidStatus == HEAP_XMAX_COMMITTED)) { if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple))) { *************** *** 1240,1246 **** * invalid, then we assume it's still alive (since the presumption is that * all relevant hint bits were just set moments ago). */ ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED)) return (tuple->t_infomask & HEAP_XMIN_INVALID) != 0 ? true : false; /* --- 1273,1281 ---- * invalid, then we assume it's still alive (since the presumption is that * all relevant hint bits were just set moments ago). */ ! if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED) ! && !(cachedVisibilityXid == HeapTupleHeaderGetXmin(tuple) ! && cachedVisibilityXidStatus == HEAP_XMIN_COMMITTED)) return (tuple->t_infomask & HEAP_XMIN_INVALID) != 0 ? true : false; /* *************** *** 1253,1259 **** return false; /* If deleter isn't known to have committed, assume it's still running. */ ! if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) return false; /* Deleter committed, so tuple is dead if the XID is old enough. */ --- 1288,1296 ---- return false; /* If deleter isn't known to have committed, assume it's still running. */ ! if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED) ! && !(cachedVisibilityXid == HeapTupleHeaderGetXmax(tuple) ! && cachedVisibilityXidStatus == HEAP_XMAX_COMMITTED)) return false; /* Deleter committed, so tuple is dead if the XID is old enough. */