diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c new file mode 100644 index c5732c3..a13f243 *** a/src/backend/access/gin/ginfast.c --- b/src/backend/access/gin/ginfast.c *************** *** 24,29 **** --- 24,30 ---- #include "miscadmin.h" #include "utils/memutils.h" #include "utils/rel.h" + #include "storage/indexfsm.h" /* GUC parameter */ int gin_pending_list_limit = 0; *************** shiftList(Relation index, Buffer metabuf *** 521,530 **** --- 522,533 ---- 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]); *************** shiftList(Relation index, Buffer metabuf *** 609,614 **** --- 612,621 ---- UnlockReleaseBuffer(buffers[i]); END_CRIT_SECTION(); + + for (i = 0; i < data.ndeleted; i++) + RecordFreeIndexPage(index, freespace[i]); + } while (blknoToDelete != newHead); return false; *************** ginInsertCleanup(GinState *ginstate, *** 744,749 **** --- 751,757 ---- BuildAccumulator accum; KeyArray datums; BlockNumber blkno; + bool fsm_vac = false; metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO); LockBuffer(metabuffer, GIN_SHARE); *************** ginInsertCleanup(GinState *ginstate, *** 793,798 **** --- 801,807 ---- { /* another cleanup process is running concurrently */ UnlockReleaseBuffer(buffer); + fsm_vac = false; break; } *************** ginInsertCleanup(GinState *ginstate, *** 857,862 **** --- 866,872 ---- /* another cleanup process is running concurrently */ UnlockReleaseBuffer(buffer); LockBuffer(metabuffer, GIN_UNLOCK); + fsm_vac = false; break; } *************** ginInsertCleanup(GinState *ginstate, *** 895,903 **** --- 905,917 ---- { /* 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); *************** ginInsertCleanup(GinState *ginstate, *** 931,936 **** --- 945,959 ---- 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);