|
24 | 24 | #include"miscadmin.h"
|
25 | 25 | #include"utils/memutils.h"
|
26 | 26 | #include"utils/rel.h"
|
| 27 | +#include"storage/indexfsm.h" |
27 | 28 |
|
28 | 29 | /* GUC parameter */
|
29 | 30 | intgin_pending_list_limit=0;
|
@@ -521,10 +522,12 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
|
521 | 522 | int64nDeletedHeapTuples=0;
|
522 | 523 | ginxlogDeleteListPagesdata;
|
523 | 524 | Bufferbuffers[GIN_NDELETE_AT_ONCE];
|
| 525 | +BlockNumberfreespace[GIN_NDELETE_AT_ONCE]; |
524 | 526 |
|
525 | 527 | data.ndeleted=0;
|
526 | 528 | while (data.ndeleted<GIN_NDELETE_AT_ONCE&&blknoToDelete!=newHead)
|
527 | 529 | {
|
| 530 | +freespace[data.ndeleted]=blknoToDelete; |
528 | 531 | buffers[data.ndeleted]=ReadBuffer(index,blknoToDelete);
|
529 | 532 | LockBuffer(buffers[data.ndeleted],GIN_EXCLUSIVE);
|
530 | 533 | page=BufferGetPage(buffers[data.ndeleted]);
|
@@ -609,6 +612,10 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
|
609 | 612 | UnlockReleaseBuffer(buffers[i]);
|
610 | 613 |
|
611 | 614 | END_CRIT_SECTION();
|
| 615 | + |
| 616 | +for (i=0;i<data.ndeleted;i++) |
| 617 | +RecordFreeIndexPage(index,freespace[i]); |
| 618 | + |
612 | 619 | }while (blknoToDelete!=newHead);
|
613 | 620 |
|
614 | 621 | return false;
|
@@ -744,6 +751,7 @@ ginInsertCleanup(GinState *ginstate,
|
744 | 751 | BuildAccumulatoraccum;
|
745 | 752 | KeyArraydatums;
|
746 | 753 | BlockNumberblkno;
|
| 754 | +boolfsm_vac= false; |
747 | 755 |
|
748 | 756 | metabuffer=ReadBuffer(index,GIN_METAPAGE_BLKNO);
|
749 | 757 | LockBuffer(metabuffer,GIN_SHARE);
|
@@ -793,6 +801,7 @@ ginInsertCleanup(GinState *ginstate,
|
793 | 801 | {
|
794 | 802 | /* another cleanup process is running concurrently */
|
795 | 803 | UnlockReleaseBuffer(buffer);
|
| 804 | +fsm_vac= false; |
796 | 805 | break;
|
797 | 806 | }
|
798 | 807 |
|
@@ -857,6 +866,7 @@ ginInsertCleanup(GinState *ginstate,
|
857 | 866 | /* another cleanup process is running concurrently */
|
858 | 867 | UnlockReleaseBuffer(buffer);
|
859 | 868 | LockBuffer(metabuffer,GIN_UNLOCK);
|
| 869 | +fsm_vac= false; |
860 | 870 | break;
|
861 | 871 | }
|
862 | 872 |
|
@@ -895,9 +905,13 @@ ginInsertCleanup(GinState *ginstate,
|
895 | 905 | {
|
896 | 906 | /* another cleanup process is running concurrently */
|
897 | 907 | LockBuffer(metabuffer,GIN_UNLOCK);
|
| 908 | +fsm_vac= false; |
898 | 909 | break;
|
899 | 910 | }
|
900 | 911 |
|
| 912 | +/* At this point, some pending pages have been freed up */ |
| 913 | +fsm_vac= true; |
| 914 | + |
901 | 915 | Assert(blkno==metadata->head);
|
902 | 916 | LockBuffer(metabuffer,GIN_UNLOCK);
|
903 | 917 |
|
@@ -931,6 +945,15 @@ ginInsertCleanup(GinState *ginstate,
|
931 | 945 |
|
932 | 946 | ReleaseBuffer(metabuffer);
|
933 | 947 |
|
| 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 | + |
934 | 957 | /* Clean up temporary space */
|
935 | 958 | MemoryContextSwitchTo(oldCtx);
|
936 | 959 | MemoryContextDelete(opCtx);
|
|