Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e956808

Browse files
committed
Add pages deleted from pending list to FSM
Add pages deleted from GIN's pending list during cleanup to free space map immediately. Clean up process could be initiated by ordinary insert but adding page to FSM might occur only at vacuum. On some workload like never-vacuumed insert-only tables it could cause a huge bloat. Jeff Janes <jeff.janes@gmail.com>
1 parent a1c44e1 commit e956808

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

src/backend/access/gin/ginfast.c

+23
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "miscadmin.h"
2525
#include "utils/memutils.h"
2626
#include "utils/rel.h"
27+
#include "storage/indexfsm.h"
2728

2829
/* GUC parameter */
2930
int gin_pending_list_limit = 0;
@@ -521,10 +522,12 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
521522
int64 nDeletedHeapTuples = 0;
522523
ginxlogDeleteListPages data;
523524
Buffer buffers[GIN_NDELETE_AT_ONCE];
525+
BlockNumber freespace[GIN_NDELETE_AT_ONCE];
524526

525527
data.ndeleted = 0;
526528
while (data.ndeleted < GIN_NDELETE_AT_ONCE && blknoToDelete != newHead)
527529
{
530+
freespace[data.ndeleted] = blknoToDelete;
528531
buffers[data.ndeleted] = ReadBuffer(index, blknoToDelete);
529532
LockBuffer(buffers[data.ndeleted], GIN_EXCLUSIVE);
530533
page = BufferGetPage(buffers[data.ndeleted]);
@@ -609,6 +612,10 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
609612
UnlockReleaseBuffer(buffers[i]);
610613

611614
END_CRIT_SECTION();
615+
616+
for (i = 0; i < data.ndeleted; i++)
617+
RecordFreeIndexPage(index, freespace[i]);
618+
612619
} while (blknoToDelete != newHead);
613620

614621
return false;
@@ -744,6 +751,7 @@ ginInsertCleanup(GinState *ginstate,
744751
BuildAccumulator accum;
745752
KeyArray datums;
746753
BlockNumber blkno;
754+
bool fsm_vac = false;
747755

748756
metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO);
749757
LockBuffer(metabuffer, GIN_SHARE);
@@ -793,6 +801,7 @@ ginInsertCleanup(GinState *ginstate,
793801
{
794802
/* another cleanup process is running concurrently */
795803
UnlockReleaseBuffer(buffer);
804+
fsm_vac = false;
796805
break;
797806
}
798807

@@ -857,6 +866,7 @@ ginInsertCleanup(GinState *ginstate,
857866
/* another cleanup process is running concurrently */
858867
UnlockReleaseBuffer(buffer);
859868
LockBuffer(metabuffer, GIN_UNLOCK);
869+
fsm_vac = false;
860870
break;
861871
}
862872

@@ -895,9 +905,13 @@ ginInsertCleanup(GinState *ginstate,
895905
{
896906
/* another cleanup process is running concurrently */
897907
LockBuffer(metabuffer, GIN_UNLOCK);
908+
fsm_vac = false;
898909
break;
899910
}
900911

912+
/* At this point, some pending pages have been freed up */
913+
fsm_vac = true;
914+
901915
Assert(blkno == metadata->head);
902916
LockBuffer(metabuffer, GIN_UNLOCK);
903917

@@ -931,6 +945,15 @@ ginInsertCleanup(GinState *ginstate,
931945

932946
ReleaseBuffer(metabuffer);
933947

948+
/*
949+
* As pending list pages can have a high churn rate, it is
950+
* desirable to recycle them immediately to the FreeSpace Map when
951+
* ordinary backends clean the list.
952+
*/
953+
if (fsm_vac && !vac_delay)
954+
IndexFreeSpaceMapVacuum(index);
955+
956+
934957
/* Clean up temporary space */
935958
MemoryContextSwitchTo(oldCtx);
936959
MemoryContextDelete(opCtx);

0 commit comments

Comments
 (0)