Skip to content

Commit dc6acfd

Browse files
Count pages set all-visible and all-frozen in VM during vacuum
Heap vacuum already counts and logs pages with newly frozen tuples. Now count and log the number of pages newly set all-visible and all-frozen in the visibility map. Pages that are all-visible but not all-frozen are debt for future aggressive vacuums. The counts of newly all-visible and all-frozen pages give us insight into the rate at which this debt is being accrued and paid down. Author: Melanie Plageman Reviewed-by: Masahiko Sawada, Alastair Turner, Nitin Jadhav, Andres Freund, Bilal Yavuz, Tomas Vondra Discussion: https://postgr.es/m/flat/CAAKRu_ZQe26xdvAqo4weHLR%3DivQ8J4xrSfDDD8uXnh-O-6P6Lg%40mail.gmail.com#6d8d2b4219394f774889509bf3bdc13d, https://postgr.es/m/ctdjzroezaxmiyah3gwbwm67defsrwj2b5fpfs4ku6msfpxeia%40mwjyqlhwr2wu
1 parent 4b565a1 commit dc6acfd

File tree

1 file changed

+111
-12
lines changed

1 file changed

+111
-12
lines changed

src/backend/access/heap/vacuumlazy.c

Lines changed: 111 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,21 @@ typedef struct LVRelState
189189
BlockNumber scanned_pages; /* # pages examined (not skipped via VM) */
190190
BlockNumber removed_pages; /* # pages removed by relation truncation */
191191
BlockNumber new_frozen_tuple_pages; /* # pages with newly frozen tuples */
192+
193+
/* # pages newly set all-visible in the VM */
194+
BlockNumber vm_new_visible_pages;
195+
196+
/*
197+
* # pages newly set all-visible and all-frozen in the VM. This is a
198+
* subset of vm_new_visible_pages. That is, vm_new_visible_pages includes
199+
* all pages set all-visible, but vm_new_visible_frozen_pages includes
200+
* only those which were also set all-frozen.
201+
*/
202+
BlockNumber vm_new_visible_frozen_pages;
203+
204+
/* # all-visible pages newly set all-frozen in the VM */
205+
BlockNumber vm_new_frozen_pages;
206+
192207
BlockNumber lpdead_item_pages; /* # pages with LP_DEAD items */
193208
BlockNumber missed_dead_pages; /* # pages with missed dead tuples */
194209
BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */
@@ -428,6 +443,10 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
428443
vacrel->recently_dead_tuples = 0;
429444
vacrel->missed_dead_tuples = 0;
430445

446+
vacrel->vm_new_visible_pages = 0;
447+
vacrel->vm_new_visible_frozen_pages = 0;
448+
vacrel->vm_new_frozen_pages = 0;
449+
431450
/*
432451
* Get cutoffs that determine which deleted tuples are considered DEAD,
433452
* not just RECENTLY_DEAD, and which XIDs/MXIDs to freeze. Then determine
@@ -701,6 +720,13 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
701720
100.0 * vacrel->new_frozen_tuple_pages /
702721
orig_rel_pages,
703722
(long long) vacrel->tuples_frozen);
723+
724+
appendStringInfo(&buf,
725+
_("visibility map: %u pages set all-visible, %u pages set all-frozen (%u were all-visible)\n"),
726+
vacrel->vm_new_visible_pages,
727+
vacrel->vm_new_visible_frozen_pages +
728+
vacrel->vm_new_frozen_pages,
729+
vacrel->vm_new_frozen_pages);
704730
if (vacrel->do_index_vacuuming)
705731
{
706732
if (vacrel->nindexes == 0 || vacrel->num_index_scans == 0)
@@ -1354,6 +1380,8 @@ lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno,
13541380
*/
13551381
if (!PageIsAllVisible(page))
13561382
{
1383+
uint8 old_vmbits;
1384+
13571385
START_CRIT_SECTION();
13581386

13591387
/* mark buffer dirty before writing a WAL record */
@@ -1373,10 +1401,24 @@ lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno,
13731401
log_newpage_buffer(buf, true);
13741402

13751403
PageSetAllVisible(page);
1376-
visibilitymap_set(vacrel->rel, blkno, buf, InvalidXLogRecPtr,
1377-
vmbuffer, InvalidTransactionId,
1378-
VISIBILITYMAP_ALL_VISIBLE | VISIBILITYMAP_ALL_FROZEN);
1404+
old_vmbits = visibilitymap_set(vacrel->rel, blkno, buf,
1405+
InvalidXLogRecPtr,
1406+
vmbuffer, InvalidTransactionId,
1407+
VISIBILITYMAP_ALL_VISIBLE |
1408+
VISIBILITYMAP_ALL_FROZEN);
13791409
END_CRIT_SECTION();
1410+
1411+
/*
1412+
* If the page wasn't already set all-visible and/or all-frozen in
1413+
* the VM, count it as newly set for logging.
1414+
*/
1415+
if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0)
1416+
{
1417+
vacrel->vm_new_visible_pages++;
1418+
vacrel->vm_new_visible_frozen_pages++;
1419+
}
1420+
else if ((old_vmbits & VISIBILITYMAP_ALL_FROZEN) == 0)
1421+
vacrel->vm_new_frozen_pages++;
13801422
}
13811423

13821424
freespace = PageGetHeapFreeSpace(page);
@@ -1531,6 +1573,7 @@ lazy_scan_prune(LVRelState *vacrel,
15311573
*/
15321574
if (!all_visible_according_to_vm && presult.all_visible)
15331575
{
1576+
uint8 old_vmbits;
15341577
uint8 flags = VISIBILITYMAP_ALL_VISIBLE;
15351578

15361579
if (presult.all_frozen)
@@ -1554,9 +1597,24 @@ lazy_scan_prune(LVRelState *vacrel,
15541597
*/
15551598
PageSetAllVisible(page);
15561599
MarkBufferDirty(buf);
1557-
visibilitymap_set(vacrel->rel, blkno, buf, InvalidXLogRecPtr,
1558-
vmbuffer, presult.vm_conflict_horizon,
1559-
flags);
1600+
old_vmbits = visibilitymap_set(vacrel->rel, blkno, buf,
1601+
InvalidXLogRecPtr,
1602+
vmbuffer, presult.vm_conflict_horizon,
1603+
flags);
1604+
1605+
/*
1606+
* If the page wasn't already set all-visible and/or all-frozen in the
1607+
* VM, count it as newly set for logging.
1608+
*/
1609+
if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0)
1610+
{
1611+
vacrel->vm_new_visible_pages++;
1612+
if (presult.all_frozen)
1613+
vacrel->vm_new_visible_frozen_pages++;
1614+
}
1615+
else if ((old_vmbits & VISIBILITYMAP_ALL_FROZEN) == 0 &&
1616+
presult.all_frozen)
1617+
vacrel->vm_new_frozen_pages++;
15601618
}
15611619

15621620
/*
@@ -1606,6 +1664,8 @@ lazy_scan_prune(LVRelState *vacrel,
16061664
else if (all_visible_according_to_vm && presult.all_visible &&
16071665
presult.all_frozen && !VM_ALL_FROZEN(vacrel->rel, blkno, &vmbuffer))
16081666
{
1667+
uint8 old_vmbits;
1668+
16091669
/*
16101670
* Avoid relying on all_visible_according_to_vm as a proxy for the
16111671
* page-level PD_ALL_VISIBLE bit being set, since it might have become
@@ -1625,10 +1685,31 @@ lazy_scan_prune(LVRelState *vacrel,
16251685
* was logged when the page's tuples were frozen.
16261686
*/
16271687
Assert(!TransactionIdIsValid(presult.vm_conflict_horizon));
1628-
visibilitymap_set(vacrel->rel, blkno, buf, InvalidXLogRecPtr,
1629-
vmbuffer, InvalidTransactionId,
1630-
VISIBILITYMAP_ALL_VISIBLE |
1631-
VISIBILITYMAP_ALL_FROZEN);
1688+
old_vmbits = visibilitymap_set(vacrel->rel, blkno, buf,
1689+
InvalidXLogRecPtr,
1690+
vmbuffer, InvalidTransactionId,
1691+
VISIBILITYMAP_ALL_VISIBLE |
1692+
VISIBILITYMAP_ALL_FROZEN);
1693+
1694+
/*
1695+
* The page was likely already set all-visible in the VM. However,
1696+
* there is a small chance that it was modified sometime between
1697+
* setting all_visible_according_to_vm and checking the visibility
1698+
* during pruning. Check the return value of old_vmbits anyway to
1699+
* ensure the visibility map counters used for logging are accurate.
1700+
*/
1701+
if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0)
1702+
{
1703+
vacrel->vm_new_visible_pages++;
1704+
vacrel->vm_new_visible_frozen_pages++;
1705+
}
1706+
1707+
/*
1708+
* We already checked that the page was not set all-frozen in the VM
1709+
* above, so we don't need to test the value of old_vmbits.
1710+
*/
1711+
else
1712+
vacrel->vm_new_frozen_pages++;
16321713
}
16331714
}
16341715

@@ -2274,6 +2355,7 @@ lazy_vacuum_heap_page(LVRelState *vacrel, BlockNumber blkno, Buffer buffer,
22742355
if (heap_page_is_all_visible(vacrel, buffer, &visibility_cutoff_xid,
22752356
&all_frozen))
22762357
{
2358+
uint8 old_vmbits;
22772359
uint8 flags = VISIBILITYMAP_ALL_VISIBLE;
22782360

22792361
if (all_frozen)
@@ -2283,8 +2365,25 @@ lazy_vacuum_heap_page(LVRelState *vacrel, BlockNumber blkno, Buffer buffer,
22832365
}
22842366

22852367
PageSetAllVisible(page);
2286-
visibilitymap_set(vacrel->rel, blkno, buffer, InvalidXLogRecPtr,
2287-
vmbuffer, visibility_cutoff_xid, flags);
2368+
old_vmbits = visibilitymap_set(vacrel->rel, blkno, buffer,
2369+
InvalidXLogRecPtr,
2370+
vmbuffer, visibility_cutoff_xid,
2371+
flags);
2372+
2373+
/*
2374+
* If the page wasn't already set all-visible and/or all-frozen in the
2375+
* VM, count it as newly set for logging.
2376+
*/
2377+
if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0)
2378+
{
2379+
vacrel->vm_new_visible_pages++;
2380+
if (all_frozen)
2381+
vacrel->vm_new_visible_frozen_pages++;
2382+
}
2383+
2384+
else if ((old_vmbits & VISIBILITYMAP_ALL_FROZEN) == 0 &&
2385+
all_frozen)
2386+
vacrel->vm_new_frozen_pages++;
22882387
}
22892388

22902389
/* Revert to the previous phase information for error traceback */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy