Skip to content

Commit 45d395c

Browse files
committed
Be more consistent about whether to update the FSM while vacuuming.
Previously, when lazy_scan_noprune() was called and returned true, we would update the FSM immediately if the relation had no indexes or if the page contained no dead items. On the other hand, when lazy_scan_prune() was called, we would update the FSM if either of those things was true or if index vacuuming was disabled. Eliminate that behavioral difference by considering vacrel->do_index_vacuuming in both cases. Also, make lazy_scan_heap() responsible for deciding whether to update the FSM, instead of doing it inside lazy_scan_noprune(). This is more consistent with the lazy_scan_prune() case. lazy_scan_noprune() still needs an output parameter for whether there are LP_DEAD items on the page, but the real decision-making now happens in the caller. Patch by me, reviewed by Peter Geoghegan and Melanie Plageman. Discussion: http://postgr.es/m/CA+TgmoaOzvN1TcHd9iej=PR3fY40En1USxzOnXSR2CxCLaRM0g@mail.gmail.com
1 parent 6995863 commit 45d395c

File tree

1 file changed

+30
-29
lines changed

1 file changed

+30
-29
lines changed

src/backend/access/heap/vacuumlazy.c

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ static void lazy_scan_prune(LVRelState *vacrel, Buffer buf,
252252
LVPagePruneState *prunestate);
253253
static bool lazy_scan_noprune(LVRelState *vacrel, Buffer buf,
254254
BlockNumber blkno, Page page,
255-
bool *recordfreespace);
255+
bool *has_lpdead_items);
256256
static void lazy_vacuum(LVRelState *vacrel);
257257
static bool lazy_vacuum_all_indexes(LVRelState *vacrel);
258258
static void lazy_vacuum_heap_rel(LVRelState *vacrel);
@@ -958,7 +958,7 @@ lazy_scan_heap(LVRelState *vacrel)
958958
page = BufferGetPage(buf);
959959
if (!ConditionalLockBufferForCleanup(buf))
960960
{
961-
bool recordfreespace;
961+
bool has_lpdead_items;
962962

963963
LockBuffer(buf, BUFFER_LOCK_SHARE);
964964

@@ -974,17 +974,30 @@ lazy_scan_heap(LVRelState *vacrel)
974974
* Collect LP_DEAD items in dead_items array, count tuples,
975975
* determine if rel truncation is safe
976976
*/
977-
if (lazy_scan_noprune(vacrel, buf, blkno, page,
978-
&recordfreespace))
977+
if (lazy_scan_noprune(vacrel, buf, blkno, page, &has_lpdead_items))
979978
{
980979
Size freespace = 0;
980+
bool recordfreespace;
981981

982982
/*
983-
* Processed page successfully (without cleanup lock) -- just
984-
* need to update the FSM, much like the lazy_scan_prune case.
985-
* Don't bother trying to match its visibility map setting
986-
* steps, though.
983+
* We processed the page successfully (without a cleanup
984+
* lock).
985+
*
986+
* Update the FSM, just as we would in the case where
987+
* lazy_scan_prune() is called. Our goal is to update the
988+
* freespace map the last time we touch the page. If the
989+
* relation has no indexes, or if index vacuuming is disabled,
990+
* there will be no second heap pass; if this particular page
991+
* has no dead items, the second heap pass will not touch this
992+
* page. So, in those cases, update the FSM now.
993+
*
994+
* After a call to lazy_scan_prune(), we would also try to
995+
* adjust the page-level all-visible bit and the visibility
996+
* map, but we skip that step in this path.
987997
*/
998+
recordfreespace = vacrel->nindexes == 0
999+
|| !vacrel->do_index_vacuuming
1000+
|| !has_lpdead_items;
9881001
if (recordfreespace)
9891002
freespace = PageGetHeapFreeSpace(page);
9901003
UnlockReleaseBuffer(buf);
@@ -1935,15 +1948,17 @@ lazy_scan_prune(LVRelState *vacrel,
19351948
* one or more tuples on the page. We always return true for non-aggressive
19361949
* callers.
19371950
*
1938-
* recordfreespace flag instructs caller on whether or not it should do
1939-
* generic FSM processing for page.
1951+
* If this function returns true, *has_lpdead_items gets set to true or false
1952+
* depending on whether, upon return from this function, any LP_DEAD items are
1953+
* present on the page. If this function returns false, *has_lpdead_items
1954+
* is not updated.
19401955
*/
19411956
static bool
19421957
lazy_scan_noprune(LVRelState *vacrel,
19431958
Buffer buf,
19441959
BlockNumber blkno,
19451960
Page page,
1946-
bool *recordfreespace)
1961+
bool *has_lpdead_items)
19471962
{
19481963
OffsetNumber offnum,
19491964
maxoff;
@@ -1960,7 +1975,6 @@ lazy_scan_noprune(LVRelState *vacrel,
19601975
Assert(BufferGetBlockNumber(buf) == blkno);
19611976

19621977
hastup = false; /* for now */
1963-
*recordfreespace = false; /* for now */
19641978

19651979
lpdead_items = 0;
19661980
live_tuples = 0;
@@ -2102,18 +2116,8 @@ lazy_scan_noprune(LVRelState *vacrel,
21022116
hastup = true;
21032117
missed_dead_tuples += lpdead_items;
21042118
}
2105-
2106-
*recordfreespace = true;
2107-
}
2108-
else if (lpdead_items == 0)
2109-
{
2110-
/*
2111-
* Won't be vacuuming this page later, so record page's freespace in
2112-
* the FSM now
2113-
*/
2114-
*recordfreespace = true;
21152119
}
2116-
else
2120+
else if (lpdead_items > 0)
21172121
{
21182122
VacDeadItems *dead_items = vacrel->dead_items;
21192123
ItemPointerData tmp;
@@ -2138,12 +2142,6 @@ lazy_scan_noprune(LVRelState *vacrel,
21382142
dead_items->num_items);
21392143

21402144
vacrel->lpdead_items += lpdead_items;
2141-
2142-
/*
2143-
* Assume that we'll go on to vacuum this heap page during final pass
2144-
* over the heap. Don't record free space until then.
2145-
*/
2146-
*recordfreespace = false;
21472145
}
21482146

21492147
/*
@@ -2159,6 +2157,9 @@ lazy_scan_noprune(LVRelState *vacrel,
21592157
if (hastup)
21602158
vacrel->nonempty_pages = blkno + 1;
21612159

2160+
/* Did we find LP_DEAD items? */
2161+
*has_lpdead_items = (lpdead_items > 0);
2162+
21622163
/* Caller won't need to call lazy_scan_prune with same page */
21632164
return true;
21642165
}

0 commit comments

Comments
 (0)