diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c index ae446653a9..fa8d8a756e 100644 --- a/src/backend/access/gin/ginfast.c +++ b/src/backend/access/gin/ginfast.c @@ -24,6 +24,7 @@ #include "miscadmin.h" #include "utils/memutils.h" #include "utils/rel.h" +#include "storage/indexfsm.h" /* GUC parameter */ int gin_pending_list_limit = 0; @@ -521,10 +522,12 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead, int64 nDeletedHeapTuples = 0; ginxlogDeleteListPages data; Buffer buffers[GIN_NDELETE_AT_ONCE]; + BlockNumber freespace[GIN_NDELETE_AT_ONCE]; data.ndeleted = 0; while (data.ndeleted < GIN_NDELETE_AT_ONCE && blknoToDelete != newHead) { + freespace[data.ndeleted] = blknoToDelete; buffers[data.ndeleted] = ReadBuffer(index, blknoToDelete); LockBuffer(buffers[data.ndeleted], GIN_EXCLUSIVE); page = BufferGetPage(buffers[data.ndeleted]); @@ -609,6 +612,10 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead, UnlockReleaseBuffer(buffers[i]); END_CRIT_SECTION(); + + for (i = 0; i < data.ndeleted; i++) + RecordFreeIndexPage(index, freespace[i]); + } while (blknoToDelete != newHead); return false; @@ -744,6 +751,7 @@ ginInsertCleanup(GinState *ginstate, BuildAccumulator accum; KeyArray datums; BlockNumber blkno; + bool fsm_vac = false; metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO); LockBuffer(metabuffer, GIN_SHARE); @@ -793,6 +801,7 @@ ginInsertCleanup(GinState *ginstate, { /* another cleanup process is running concurrently */ UnlockReleaseBuffer(buffer); + fsm_vac = false; break; } @@ -857,6 +866,7 @@ ginInsertCleanup(GinState *ginstate, /* another cleanup process is running concurrently */ UnlockReleaseBuffer(buffer); LockBuffer(metabuffer, GIN_UNLOCK); + fsm_vac = false; break; } @@ -895,9 +905,13 @@ ginInsertCleanup(GinState *ginstate, { /* another cleanup process is running concurrently */ LockBuffer(metabuffer, GIN_UNLOCK); + fsm_vac = false; break; } + /* At this point, some pending pages have been freed up */ + fsm_vac = true; + Assert(blkno == metadata->head); LockBuffer(metabuffer, GIN_UNLOCK); @@ -931,6 +945,15 @@ ginInsertCleanup(GinState *ginstate, ReleaseBuffer(metabuffer); + /* + * As pending list pages can have a high churn rate, it is + * desirable to recycle them immediately to the FreeSpace Map when + * ordinary backends clean the list. + */ + if (fsm_vac && !vac_delay) + IndexFreeSpaceMapVacuum(index); + + /* Clean up temporary space */ MemoryContextSwitchTo(oldCtx); MemoryContextDelete(opCtx);