mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
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
This commit is contained in:
parent
6995863157
commit
45d395cd75
@ -252,7 +252,7 @@ static void lazy_scan_prune(LVRelState *vacrel, Buffer buf,
|
|||||||
LVPagePruneState *prunestate);
|
LVPagePruneState *prunestate);
|
||||||
static bool lazy_scan_noprune(LVRelState *vacrel, Buffer buf,
|
static bool lazy_scan_noprune(LVRelState *vacrel, Buffer buf,
|
||||||
BlockNumber blkno, Page page,
|
BlockNumber blkno, Page page,
|
||||||
bool *recordfreespace);
|
bool *has_lpdead_items);
|
||||||
static void lazy_vacuum(LVRelState *vacrel);
|
static void lazy_vacuum(LVRelState *vacrel);
|
||||||
static bool lazy_vacuum_all_indexes(LVRelState *vacrel);
|
static bool lazy_vacuum_all_indexes(LVRelState *vacrel);
|
||||||
static void lazy_vacuum_heap_rel(LVRelState *vacrel);
|
static void lazy_vacuum_heap_rel(LVRelState *vacrel);
|
||||||
@ -958,7 +958,7 @@ lazy_scan_heap(LVRelState *vacrel)
|
|||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
if (!ConditionalLockBufferForCleanup(buf))
|
if (!ConditionalLockBufferForCleanup(buf))
|
||||||
{
|
{
|
||||||
bool recordfreespace;
|
bool has_lpdead_items;
|
||||||
|
|
||||||
LockBuffer(buf, BUFFER_LOCK_SHARE);
|
LockBuffer(buf, BUFFER_LOCK_SHARE);
|
||||||
|
|
||||||
@ -974,17 +974,30 @@ lazy_scan_heap(LVRelState *vacrel)
|
|||||||
* Collect LP_DEAD items in dead_items array, count tuples,
|
* Collect LP_DEAD items in dead_items array, count tuples,
|
||||||
* determine if rel truncation is safe
|
* determine if rel truncation is safe
|
||||||
*/
|
*/
|
||||||
if (lazy_scan_noprune(vacrel, buf, blkno, page,
|
if (lazy_scan_noprune(vacrel, buf, blkno, page, &has_lpdead_items))
|
||||||
&recordfreespace))
|
|
||||||
{
|
{
|
||||||
Size freespace = 0;
|
Size freespace = 0;
|
||||||
|
bool recordfreespace;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Processed page successfully (without cleanup lock) -- just
|
* We processed the page successfully (without a cleanup
|
||||||
* need to update the FSM, much like the lazy_scan_prune case.
|
* lock).
|
||||||
* Don't bother trying to match its visibility map setting
|
*
|
||||||
* steps, though.
|
* Update the FSM, just as we would in the case where
|
||||||
|
* lazy_scan_prune() is called. Our goal is to update the
|
||||||
|
* freespace map the last time we touch the page. If the
|
||||||
|
* relation has no indexes, or if index vacuuming is disabled,
|
||||||
|
* there will be no second heap pass; if this particular page
|
||||||
|
* has no dead items, the second heap pass will not touch this
|
||||||
|
* page. So, in those cases, update the FSM now.
|
||||||
|
*
|
||||||
|
* After a call to lazy_scan_prune(), we would also try to
|
||||||
|
* adjust the page-level all-visible bit and the visibility
|
||||||
|
* map, but we skip that step in this path.
|
||||||
*/
|
*/
|
||||||
|
recordfreespace = vacrel->nindexes == 0
|
||||||
|
|| !vacrel->do_index_vacuuming
|
||||||
|
|| !has_lpdead_items;
|
||||||
if (recordfreespace)
|
if (recordfreespace)
|
||||||
freespace = PageGetHeapFreeSpace(page);
|
freespace = PageGetHeapFreeSpace(page);
|
||||||
UnlockReleaseBuffer(buf);
|
UnlockReleaseBuffer(buf);
|
||||||
@ -1935,15 +1948,17 @@ lazy_scan_prune(LVRelState *vacrel,
|
|||||||
* one or more tuples on the page. We always return true for non-aggressive
|
* one or more tuples on the page. We always return true for non-aggressive
|
||||||
* callers.
|
* callers.
|
||||||
*
|
*
|
||||||
* recordfreespace flag instructs caller on whether or not it should do
|
* If this function returns true, *has_lpdead_items gets set to true or false
|
||||||
* generic FSM processing for page.
|
* depending on whether, upon return from this function, any LP_DEAD items are
|
||||||
|
* present on the page. If this function returns false, *has_lpdead_items
|
||||||
|
* is not updated.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
lazy_scan_noprune(LVRelState *vacrel,
|
lazy_scan_noprune(LVRelState *vacrel,
|
||||||
Buffer buf,
|
Buffer buf,
|
||||||
BlockNumber blkno,
|
BlockNumber blkno,
|
||||||
Page page,
|
Page page,
|
||||||
bool *recordfreespace)
|
bool *has_lpdead_items)
|
||||||
{
|
{
|
||||||
OffsetNumber offnum,
|
OffsetNumber offnum,
|
||||||
maxoff;
|
maxoff;
|
||||||
@ -1960,7 +1975,6 @@ lazy_scan_noprune(LVRelState *vacrel,
|
|||||||
Assert(BufferGetBlockNumber(buf) == blkno);
|
Assert(BufferGetBlockNumber(buf) == blkno);
|
||||||
|
|
||||||
hastup = false; /* for now */
|
hastup = false; /* for now */
|
||||||
*recordfreespace = false; /* for now */
|
|
||||||
|
|
||||||
lpdead_items = 0;
|
lpdead_items = 0;
|
||||||
live_tuples = 0;
|
live_tuples = 0;
|
||||||
@ -2102,18 +2116,8 @@ lazy_scan_noprune(LVRelState *vacrel,
|
|||||||
hastup = true;
|
hastup = true;
|
||||||
missed_dead_tuples += lpdead_items;
|
missed_dead_tuples += lpdead_items;
|
||||||
}
|
}
|
||||||
|
|
||||||
*recordfreespace = true;
|
|
||||||
}
|
}
|
||||||
else if (lpdead_items == 0)
|
else if (lpdead_items > 0)
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Won't be vacuuming this page later, so record page's freespace in
|
|
||||||
* the FSM now
|
|
||||||
*/
|
|
||||||
*recordfreespace = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
VacDeadItems *dead_items = vacrel->dead_items;
|
VacDeadItems *dead_items = vacrel->dead_items;
|
||||||
ItemPointerData tmp;
|
ItemPointerData tmp;
|
||||||
@ -2138,12 +2142,6 @@ lazy_scan_noprune(LVRelState *vacrel,
|
|||||||
dead_items->num_items);
|
dead_items->num_items);
|
||||||
|
|
||||||
vacrel->lpdead_items += lpdead_items;
|
vacrel->lpdead_items += lpdead_items;
|
||||||
|
|
||||||
/*
|
|
||||||
* Assume that we'll go on to vacuum this heap page during final pass
|
|
||||||
* over the heap. Don't record free space until then.
|
|
||||||
*/
|
|
||||||
*recordfreespace = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2159,6 +2157,9 @@ lazy_scan_noprune(LVRelState *vacrel,
|
|||||||
if (hastup)
|
if (hastup)
|
||||||
vacrel->nonempty_pages = blkno + 1;
|
vacrel->nonempty_pages = blkno + 1;
|
||||||
|
|
||||||
|
/* Did we find LP_DEAD items? */
|
||||||
|
*has_lpdead_items = (lpdead_items > 0);
|
||||||
|
|
||||||
/* Caller won't need to call lazy_scan_prune with same page */
|
/* Caller won't need to call lazy_scan_prune with same page */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user