diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index ca0d9bd917..dd2778611f 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -8349,47 +8349,6 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; - - vacuum_cleanup_index_scale_factor (floating point) - - vacuum_cleanup_index_scale_factor - configuration parameter - - - - - Specifies the fraction of the total number of heap tuples counted in - the previous statistics collection that can be inserted without - incurring an index scan at the VACUUM cleanup stage. - This setting currently applies to B-tree indexes only. - - - - If no tuples were deleted from the heap, B-tree indexes are still - scanned at the VACUUM cleanup stage when at least one - of the following conditions is met: the index statistics are stale, or - the index contains deleted pages that can be recycled during cleanup. - Index statistics are considered to be stale if the number of newly - inserted tuples exceeds the vacuum_cleanup_index_scale_factor - fraction of the total number of heap tuples detected by the previous - statistics collection. The total number of heap tuples is stored in - the index meta-page. Note that the meta-page does not include this data - until VACUUM finds no dead tuples, so B-tree index - scan at the cleanup stage can only be skipped if the second and - subsequent VACUUM cycles detect no dead tuples. - - - - The value can range from 0 to - 10000000000. - When vacuum_cleanup_index_scale_factor is set to - 0, index scans are never skipped during - VACUUM cleanup. The default value is 0.1. - - - - - bytea_output (enum) diff --git a/doc/src/sgml/ref/create_index.sgml b/doc/src/sgml/ref/create_index.sgml index 3537dfaade..5a1fd71478 100644 --- a/doc/src/sgml/ref/create_index.sgml +++ b/doc/src/sgml/ref/create_index.sgml @@ -434,20 +434,6 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] - - - vacuum_cleanup_index_scale_factor (floating point) - - vacuum_cleanup_index_scale_factor - storage parameter - - - - - Per-index value for . - - - diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index 75628e0eb9..ac6c38b155 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -168,6 +168,9 @@ _bt_getmeta(Relation rel, Buffer metabuf) * * This routine checks if provided cleanup-related information is matching * to those written in the metapage. On mismatch, metapage is overwritten. + * + * Postgres 13 ignores btm_last_cleanup_num_heap_tuples value here + * following backbranch disabling of vacuum_cleanup_index_scale_factor. */ void _bt_update_meta_cleanup_info(Relation rel, TransactionId oldestBtpoXact, @@ -176,22 +179,15 @@ _bt_update_meta_cleanup_info(Relation rel, TransactionId oldestBtpoXact, Buffer metabuf; Page metapg; BTMetaPageData *metad; - bool needsRewrite = false; - XLogRecPtr recptr; /* read the metapage and check if it needs rewrite */ metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ); metapg = BufferGetPage(metabuf); metad = BTPageGetMeta(metapg); - /* outdated version of metapage always needs rewrite */ - if (metad->btm_version < BTREE_NOVAC_VERSION) - needsRewrite = true; - else if (metad->btm_oldest_btpo_xact != oldestBtpoXact || - metad->btm_last_cleanup_num_heap_tuples != numHeapTuples) - needsRewrite = true; - - if (!needsRewrite) + /* Don't miss chance to upgrade index/metapage when BTREE_MIN_VERSION */ + if (metad->btm_version >= BTREE_NOVAC_VERSION && + metad->btm_oldest_btpo_xact == oldestBtpoXact) { _bt_relbuf(rel, metabuf); return; @@ -209,13 +205,14 @@ _bt_update_meta_cleanup_info(Relation rel, TransactionId oldestBtpoXact, /* update cleanup-related information */ metad->btm_oldest_btpo_xact = oldestBtpoXact; - metad->btm_last_cleanup_num_heap_tuples = numHeapTuples; + metad->btm_last_cleanup_num_heap_tuples = -1; MarkBufferDirty(metabuf); /* write wal record if needed */ if (RelationNeedsWAL(rel)) { xl_btree_metadata md; + XLogRecPtr recptr; XLogBeginInsert(); XLogRegisterBuffer(0, metabuf, REGBUF_WILL_INIT | REGBUF_STANDARD); @@ -227,7 +224,7 @@ _bt_update_meta_cleanup_info(Relation rel, TransactionId oldestBtpoXact, md.fastroot = metad->btm_fastroot; md.fastlevel = metad->btm_fastlevel; md.oldest_btpo_xact = oldestBtpoXact; - md.last_cleanup_num_heap_tuples = numHeapTuples; + md.last_cleanup_num_heap_tuples = -1; /* Disabled */ md.allequalimage = metad->btm_allequalimage; XLogRegisterBufData(0, (char *) &md, sizeof(xl_btree_metadata)); @@ -238,6 +235,7 @@ _bt_update_meta_cleanup_info(Relation rel, TransactionId oldestBtpoXact, } END_CRIT_SECTION(); + _bt_relbuf(rel, metabuf); } diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index d857afee1c..c37bbe53f9 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -794,6 +794,9 @@ _bt_parallel_advance_array_keys(IndexScanDesc scan) * When we return false, VACUUM can even skip the cleanup-only call to * btvacuumscan (i.e. there will be no btvacuumscan call for this index at * all). Otherwise, a cleanup-only btvacuumscan call is required. + * + * Postgres 13 ignores btm_last_cleanup_num_heap_tuples value here following + * backbranch disabling of vacuum_cleanup_index_scale_factor. */ static bool _bt_vacuum_needs_cleanup(IndexVacuumInfo *info) @@ -801,60 +804,44 @@ _bt_vacuum_needs_cleanup(IndexVacuumInfo *info) Buffer metabuf; Page metapg; BTMetaPageData *metad; - bool result = false; + uint32 btm_version; + TransactionId prev_btm_oldest_btpo_xact; + /* + * Copy details from metapage to local variables quickly. + * + * Note that we deliberately avoid using cached version of metapage here. + */ metabuf = _bt_getbuf(info->index, BTREE_METAPAGE, BT_READ); metapg = BufferGetPage(metabuf); metad = BTPageGetMeta(metapg); + btm_version = metad->btm_version; - if (metad->btm_version < BTREE_NOVAC_VERSION) + if (btm_version < BTREE_NOVAC_VERSION) { /* - * Do cleanup if metapage needs upgrade, because we don't have - * cleanup-related meta-information yet. + * Metapage needs to be dynamically upgraded to store fields that are + * only present when btm_version >= BTREE_NOVAC_VERSION */ - result = true; + _bt_relbuf(info->index, metabuf); + return true; } - else if (TransactionIdIsValid(metad->btm_oldest_btpo_xact) && - TransactionIdPrecedes(metad->btm_oldest_btpo_xact, - RecentGlobalXmin)) + + prev_btm_oldest_btpo_xact = metad->btm_oldest_btpo_xact; + _bt_relbuf(info->index, metabuf); + + if (TransactionIdIsValid(prev_btm_oldest_btpo_xact) && + TransactionIdPrecedes(prev_btm_oldest_btpo_xact, RecentGlobalXmin)) { /* * If any oldest btpo.xact from a previously deleted page in the index * is older than RecentGlobalXmin, then at least one deleted page can * be recycled -- don't skip cleanup. */ - result = true; - } - else - { - BTOptions *relopts; - float8 cleanup_scale_factor; - float8 prev_num_heap_tuples; - - /* - * If table receives enough insertions and no cleanup was performed, - * then index would appear have stale statistics. If scale factor is - * set, we avoid that by performing cleanup if the number of inserted - * tuples exceeds vacuum_cleanup_index_scale_factor fraction of - * original tuples count. - */ - relopts = (BTOptions *) info->index->rd_options; - cleanup_scale_factor = (relopts && - relopts->vacuum_cleanup_index_scale_factor >= 0) - ? relopts->vacuum_cleanup_index_scale_factor - : vacuum_cleanup_index_scale_factor; - prev_num_heap_tuples = metad->btm_last_cleanup_num_heap_tuples; - - if (cleanup_scale_factor <= 0 || - prev_num_heap_tuples <= 0 || - (info->num_heap_tuples - prev_num_heap_tuples) / - prev_num_heap_tuples >= cleanup_scale_factor) - result = true; + return true; } - _bt_relbuf(info->index, metabuf); - return result; + return false; } /* @@ -907,9 +894,6 @@ btvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) * still need to do a pass over the index, to recycle any newly-recyclable * pages or to obtain index statistics. _bt_vacuum_needs_cleanup * determines if either are needed. - * - * Since we aren't going to actually delete any leaf items, there's no - * need to go through all the vacuum-cycle-ID pushups. */ if (stats == NULL) { @@ -917,8 +901,23 @@ btvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) if (!_bt_vacuum_needs_cleanup(info)) return NULL; + /* + * Since we aren't going to actually delete any leaf items, there's no + * need to go through all the vacuum-cycle-ID pushups here. + * + * Posting list tuples are a source of inaccuracy for cleanup-only + * scans. btvacuumscan() will assume that the number of index tuples + * from each page can be used as num_index_tuples, even though + * num_index_tuples is supposed to represent the number of TIDs in the + * index. This naive approach can underestimate the number of tuples + * in the index significantly. + * + * We handle the problem by making num_index_tuples an estimate in + * cleanup-only case. + */ stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult)); btvacuumscan(info, stats, NULL, NULL, 0); + stats->estimated_count = true; } /* @@ -926,12 +925,6 @@ btvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) * double-counting some index tuples, so disbelieve any total that exceeds * the underlying heap's count ... if we know that accurately. Otherwise * this might just make matters worse. - * - * Posting list tuples are another source of inaccuracy. Cleanup-only - * btvacuumscan calls assume that the number of index tuples can be used - * as num_index_tuples, even though num_index_tuples is supposed to - * represent the number of TIDs in the index. This naive approach can - * underestimate the number of tuples in the index. */ if (!info->estimated_count) { @@ -971,7 +964,6 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, * Reset counts that will be incremented during the scan; needed in case * of multiple scans during a single VACUUM command */ - stats->estimated_count = false; stats->num_index_tuples = 0; stats->pages_deleted = 0; @@ -1059,8 +1051,12 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexFreeSpaceMapVacuum(rel); /* - * Maintain the oldest btpo.xact and a count of the current number of heap - * tuples in the metapage (for the benefit of _bt_vacuum_needs_cleanup). + * Maintain the oldest btpo.xact using _bt_update_meta_cleanup_info, for + * the benefit of _bt_vacuum_needs_cleanup. + * + * Note: We deliberately don't store the count of heap tuples here + * anymore. The numHeapTuples argument to _bt_update_meta_cleanup_info() + * is left in place on Postgres 13. * * The page with the oldest btpo.xact is typically a page deleted by this * VACUUM operation, since pages deleted by a previous VACUUM operation @@ -1070,8 +1066,7 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, * statistics, despite not counting as deleted pages for the purposes of * determining the oldest btpo.xact.) */ - _bt_update_meta_cleanup_info(rel, vstate.oldestBtpoXact, - info->num_heap_tuples); + _bt_update_meta_cleanup_info(rel, vstate.oldestBtpoXact, -1); /* update statistics */ stats->num_pages = num_pages; @@ -1399,7 +1394,10 @@ backtrack: * We don't count the number of live TIDs during cleanup-only calls to * btvacuumscan (i.e. when callback is not set). We count the number * of index tuples directly instead. This avoids the expense of - * directly examining all of the tuples on each page. + * directly examining all of the tuples on each page. VACUUM will + * treat num_index_tuples as an estimate in cleanup-only case, so it + * doesn't matter that this underestimates num_index_tuples + * significantly in some cases. */ if (minoff > maxoff) attempt_pagedel = (blkno == scanblkno); diff --git a/src/test/regress/expected/btree_index.out b/src/test/regress/expected/btree_index.out index cfd4338e36..bc113a70b4 100644 --- a/src/test/regress/expected/btree_index.out +++ b/src/test/regress/expected/btree_index.out @@ -308,35 +308,6 @@ alter table btree_tall_tbl alter COLUMN t set storage plain; create index btree_tall_idx on btree_tall_tbl (t, id) with (fillfactor = 10); insert into btree_tall_tbl select g, repeat('x', 250) from generate_series(1, 130) g; --- --- Test vacuum_cleanup_index_scale_factor --- --- Simple create -create table btree_test(a int); -create index btree_idx1 on btree_test(a) with (vacuum_cleanup_index_scale_factor = 40.0); -select reloptions from pg_class WHERE oid = 'btree_idx1'::regclass; - reloptions ------------------------------------------- - {vacuum_cleanup_index_scale_factor=40.0} -(1 row) - --- Fail while setting improper values -create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = -10.0); -ERROR: value -10.0 out of bounds for option "vacuum_cleanup_index_scale_factor" -DETAIL: Valid values are between "0.000000" and "10000000000.000000". -create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = 100.0); -create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = 'string'); -ERROR: invalid value for floating point option "vacuum_cleanup_index_scale_factor": string -create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = true); -ERROR: invalid value for floating point option "vacuum_cleanup_index_scale_factor": true --- Simple ALTER INDEX -alter index btree_idx1 set (vacuum_cleanup_index_scale_factor = 70.0); -select reloptions from pg_class WHERE oid = 'btree_idx1'::regclass; - reloptions ------------------------------------------- - {vacuum_cleanup_index_scale_factor=70.0} -(1 row) - -- -- Test for multilevel page deletion -- diff --git a/src/test/regress/sql/btree_index.sql b/src/test/regress/sql/btree_index.sql index 96f53818ff..c60312db2d 100644 --- a/src/test/regress/sql/btree_index.sql +++ b/src/test/regress/sql/btree_index.sql @@ -150,25 +150,6 @@ create index btree_tall_idx on btree_tall_tbl (t, id) with (fillfactor = 10); insert into btree_tall_tbl select g, repeat('x', 250) from generate_series(1, 130) g; --- --- Test vacuum_cleanup_index_scale_factor --- - --- Simple create -create table btree_test(a int); -create index btree_idx1 on btree_test(a) with (vacuum_cleanup_index_scale_factor = 40.0); -select reloptions from pg_class WHERE oid = 'btree_idx1'::regclass; - --- Fail while setting improper values -create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = -10.0); -create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = 100.0); -create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = 'string'); -create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = true); - --- Simple ALTER INDEX -alter index btree_idx1 set (vacuum_cleanup_index_scale_factor = 70.0); -select reloptions from pg_class WHERE oid = 'btree_idx1'::regclass; - -- -- Test for multilevel page deletion --