mirror of
https://github.com/postgres/postgres.git
synced 2025-05-31 00:01:57 -04:00
VACUUM updates leaf-level FSM entries immediately after cleaning the corresponding heap blocks. fsmpage.c updates the intra-page search trees on the leaf-level FSM pages when this happens, but it does not touch the upper-level FSM pages, so that the released space might not actually be findable by searchers. Previously, updating the upper-level pages happened only at the conclusion of the VACUUM run, in a single FreeSpaceMapVacuum() call. This is bad because the VACUUM might get canceled before ever reaching that point, so that from the point of view of searchers no space has been freed at all, leading to table bloat. We can improve matters by updating the upper pages immediately after each cycle of index-cleaning and heap-cleaning, processing just the FSM pages corresponding to the range of heap blocks we have now fully cleaned. This adds a small amount of extra work, since the FSM pages leading down to each range boundary will be touched twice, but it's pretty negligible compared to everything else going on in a large VACUUM. If there are no indexes, VACUUM doesn't work in cycles but just cleans each heap page on first visit. In that case we just arbitrarily update upper FSM pages after each 8GB of heap. That maintains the goal of not letting all this work slide until the very end, and it doesn't seem worth expending extra complexity on a case that so seldom occurs in practice. In either case, the FSM is fully up to date before any attempt is made to truncate the relation, so that the most likely scenario for VACUUM cancellation no longer results in out-of-date upper FSM pages. When we do successfully truncate, adjusting the FSM to reflect that is now fully handled within FreeSpaceMapTruncateRel. Claudio Freire, reviewed by Masahiko Sawada and Jing Wang, some additional tweaks by me Discussion: https://postgr.es/m/CAGTBQpYR0uJCNTt3M5GOzBRHo+-GccNO1nCaQ8yEJmZKSW5q1A@mail.gmail.com
43 lines
1.5 KiB
C
43 lines
1.5 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* freespace.h
|
|
* POSTGRES free space map for quickly finding free space in relations
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/storage/freespace.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef FREESPACE_H_
|
|
#define FREESPACE_H_
|
|
|
|
#include "storage/block.h"
|
|
#include "storage/relfilenode.h"
|
|
#include "utils/relcache.h"
|
|
|
|
/* prototypes for public functions in freespace.c */
|
|
extern Size GetRecordedFreeSpace(Relation rel, BlockNumber heapBlk);
|
|
extern BlockNumber GetPageWithFreeSpace(Relation rel, Size spaceNeeded);
|
|
extern BlockNumber RecordAndGetPageWithFreeSpace(Relation rel,
|
|
BlockNumber oldPage,
|
|
Size oldSpaceAvail,
|
|
Size spaceNeeded);
|
|
extern void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk,
|
|
Size spaceAvail);
|
|
extern void XLogRecordPageWithFreeSpace(RelFileNode rnode, BlockNumber heapBlk,
|
|
Size spaceAvail);
|
|
|
|
extern void FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks);
|
|
extern void FreeSpaceMapVacuum(Relation rel);
|
|
extern void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start,
|
|
BlockNumber end);
|
|
extern void UpdateFreeSpaceMap(Relation rel,
|
|
BlockNumber startBlkNum,
|
|
BlockNumber endBlkNum,
|
|
Size freespace);
|
|
|
|
#endif /* FREESPACE_H_ */
|