Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)