diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-05-30 20:12:03 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-05-30 20:12:03 +0000 |
commit | d526575f893c1a4e05ebd307e80203536b213a6d (patch) | |
tree | 529be7e5571f622bad1daab0d02de0c6669e9b81 /src/backend/access/heap/heapam.c | |
parent | 0a6f2ee84de589e14941da640fb686c7eda7be01 (diff) |
Make large sequential scans and VACUUMs work in a limited-size "ring" of
buffers, rather than blowing out the whole shared-buffer arena. Aside from
avoiding cache spoliation, this fixes the problem that VACUUM formerly tended
to cause a WAL flush for every page it modified, because we had it hacked to
use only a single buffer. Those flushes will now occur only once per
ring-ful. The exact ring size, and the threshold for seqscans to switch into
the ring usage pattern, remain under debate; but the infrastructure seems
done. The key bit of infrastructure is a new optional BufferAccessStrategy
object that can be passed to ReadBuffer operations; this replaces the former
StrategyHintVacuum API.
This patch also changes the buffer usage-count methodology a bit: we now
advance usage_count when first pinning a buffer, rather than when last
unpinning it. To preserve the behavior that a buffer's lifetime starts to
decrease when it's released, the clock sweep code is modified to not decrement
usage_count of pinned buffers.
Work not done in this commit: teach GiST and GIN indexes to use the vacuum
BufferAccessStrategy for vacuum-driven fetches.
Original patch by Simon, reworked by Heikki and again by Tom.
Diffstat (limited to 'src/backend/access/heap/heapam.c')
-rw-r--r-- | src/backend/access/heap/heapam.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 9edeaff1306..0b20e5e9a8d 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.233 2007/05/27 03:50:38 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.234 2007/05/30 20:11:53 tgl Exp $ * * * INTERFACE ROUTINES @@ -83,6 +83,24 @@ initscan(HeapScanDesc scan, ScanKey key) */ scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_rd); + /* + * If the table is large relative to NBuffers, use a bulk-read access + * strategy, else use the default random-access strategy. During a + * rescan, don't make a new strategy object if we don't have to. + */ + if (scan->rs_nblocks > NBuffers / 4 && + !scan->rs_rd->rd_istemp) + { + if (scan->rs_strategy == NULL) + scan->rs_strategy = GetAccessStrategy(BAS_BULKREAD); + } + else + { + if (scan->rs_strategy != NULL) + FreeAccessStrategy(scan->rs_strategy); + scan->rs_strategy = NULL; + } + scan->rs_inited = false; scan->rs_ctup.t_data = NULL; ItemPointerSetInvalid(&scan->rs_ctup.t_self); @@ -123,9 +141,17 @@ heapgetpage(HeapScanDesc scan, BlockNumber page) Assert(page < scan->rs_nblocks); - scan->rs_cbuf = ReleaseAndReadBuffer(scan->rs_cbuf, - scan->rs_rd, - page); + /* release previous scan buffer, if any */ + if (BufferIsValid(scan->rs_cbuf)) + { + ReleaseBuffer(scan->rs_cbuf); + scan->rs_cbuf = InvalidBuffer; + } + + /* read page using selected strategy */ + scan->rs_cbuf = ReadBufferWithStrategy(scan->rs_rd, + page, + scan->rs_strategy); scan->rs_cblock = page; if (!scan->rs_pageatatime) @@ -938,6 +964,7 @@ heap_beginscan(Relation relation, Snapshot snapshot, scan->rs_rd = relation; scan->rs_snapshot = snapshot; scan->rs_nkeys = nkeys; + scan->rs_strategy = NULL; /* set in initscan */ /* * we can use page-at-a-time mode if it's an MVCC-safe snapshot @@ -1007,6 +1034,9 @@ heap_endscan(HeapScanDesc scan) if (scan->rs_key) pfree(scan->rs_key); + if (scan->rs_strategy != NULL) + FreeAccessStrategy(scan->rs_strategy); + pfree(scan); } |