From a2b820f79f206489f3d1a9f2a97466480699f0a6 Mon Sep 17 00:00:00 2001 From: amit Date: Tue, 8 Mar 2016 15:23:38 +0900 Subject: [PATCH 3/3] WIP: Add a block number argument to index bulk delete callback. Currently, index AMs can only pass a ItemPointer (heap tid) and a generic pointer to caller specified struct. Add a BlockNumber so that the callback can use it for something. For example, lazy_tid_reaped() now uses it to track the progress of AM's bulk delete scan of an index by comparing it with the last call's value that it stores in its private state on every change. The private state being the LVRelStats struct that now has the corresponding field. On every change, the count of index blocks vacuumed is incremented which is also a new field in LVRelStats. The count is reset for every index vacuum round. Then a pgstat_progress_update_param call has been added to lazy_tid_reaped, that pushes the count on every increment. Currently, only btree AM is changed to pass the block number, others pass InvalidBlockNumber. --- src/backend/access/gin/ginvacuum.c | 2 +- src/backend/access/gist/gistvacuum.c | 2 +- src/backend/access/hash/hash.c | 2 +- src/backend/access/nbtree/nbtree.c | 2 +- src/backend/access/spgist/spgvacuum.c | 6 ++-- src/backend/catalog/index.c | 5 ++- src/backend/commands/vacuumlazy.c | 36 ++++++++++++++------------------ src/include/access/genam.h | 4 ++- 8 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c index 6a4b98a..64e69d6 100644 --- a/src/backend/access/gin/ginvacuum.c +++ b/src/backend/access/gin/ginvacuum.c @@ -55,7 +55,7 @@ ginVacuumItemPointers(GinVacuumState *gvs, ItemPointerData *items, */ for (i = 0; i < nitem; i++) { - if (gvs->callback(items + i, gvs->callback_state)) + if (gvs->callback(items + i, InvalidBlockNumber, gvs->callback_state)) { gvs->result->tuples_removed += 1; if (!tmpitems) diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c index 7947ff9..96e89c3 100644 --- a/src/backend/access/gist/gistvacuum.c +++ b/src/backend/access/gist/gistvacuum.c @@ -202,7 +202,7 @@ gistbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, iid = PageGetItemId(page, i); idxtuple = (IndexTuple) PageGetItem(page, iid); - if (callback(&(idxtuple->t_tid), callback_state)) + if (callback(&(idxtuple->t_tid), InvalidBlockNumber, callback_state)) todelete[ntodelete++] = i; else stats->num_index_tuples += 1; diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 3d48c4f..1530f0b 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -575,7 +575,7 @@ loop_top: itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offno)); htup = &(itup->t_tid); - if (callback(htup, callback_state)) + if (callback(htup, InvalidBlockNumber, callback_state)) { /* mark the item for deletion */ deletable[ndeletable++] = offno; diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index f2905cb..8c6be30 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -1034,7 +1034,7 @@ restart: * applies to *any* type of index that marks index tuples as * killed. */ - if (callback(htup, callback_state)) + if (callback(htup, blkno, callback_state)) deletable[ndeletable++] = offnum; } } diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c index 15b867f..6c7265b 100644 --- a/src/backend/access/spgist/spgvacuum.c +++ b/src/backend/access/spgist/spgvacuum.c @@ -154,7 +154,7 @@ vacuumLeafPage(spgBulkDeleteState *bds, Relation index, Buffer buffer, { Assert(ItemPointerIsValid(<->heapPtr)); - if (bds->callback(<->heapPtr, bds->callback_state)) + if (bds->callback(<->heapPtr, InvalidBlockNumber, bds->callback_state)) { bds->stats->tuples_removed += 1; deletable[i] = true; @@ -424,7 +424,7 @@ vacuumLeafRoot(spgBulkDeleteState *bds, Relation index, Buffer buffer) { Assert(ItemPointerIsValid(<->heapPtr)); - if (bds->callback(<->heapPtr, bds->callback_state)) + if (bds->callback(<->heapPtr, InvalidBlockNumber, bds->callback_state)) { bds->stats->tuples_removed += 1; toDelete[xlrec.nDelete] = i; @@ -902,7 +902,7 @@ spgbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, /* Dummy callback to delete no tuples during spgvacuumcleanup */ static bool -dummy_callback(ItemPointer itemptr, void *state) +dummy_callback(ItemPointer itemptr, BlockNumber index_blkno, void *state) { return false; } diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 31a1438..d792fdb 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -114,7 +114,8 @@ static void IndexCheckExclusion(Relation heapRelation, IndexInfo *indexInfo); static inline int64 itemptr_encode(ItemPointer itemptr); static inline void itemptr_decode(ItemPointer itemptr, int64 encoded); -static bool validate_index_callback(ItemPointer itemptr, void *opaque); +static bool validate_index_callback(ItemPointer itemptr, BlockNumber index_blkno, + void *opaque); static void validate_index_heapscan(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, @@ -2913,7 +2914,7 @@ itemptr_decode(ItemPointer itemptr, int64 encoded) * validate_index_callback - bulkdelete callback to collect the index TIDs */ static bool -validate_index_callback(ItemPointer itemptr, void *opaque) +validate_index_callback(ItemPointer itemptr, BlockNumber index_blkno, void *opaque) { v_i_state *state = (v_i_state *) opaque; int64 encoded = itemptr_encode(itemptr); diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 60c3b3b..d628822 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -143,6 +143,8 @@ typedef struct LVRelStats int num_index_scans; TransactionId latestRemovedXid; bool lock_waiter_detected; + BlockNumber last_index_blkno; + BlockNumber index_blks_vacuumed; } LVRelStats; @@ -176,7 +178,7 @@ static BlockNumber count_nondeletable_pages(Relation onerel, static void lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks); static void lazy_record_dead_tuple(LVRelStats *vacrelstats, ItemPointer itemptr); -static bool lazy_tid_reaped(ItemPointer itemptr, void *state); +static bool lazy_tid_reaped(ItemPointer itemptr, BlockNumber index_blkno, void *state); static int vac_cmp_itemptr(const void *left, const void *right); static bool heap_page_is_all_visible(Relation rel, Buffer buf, TransactionId *visibility_cutoff_xid, bool *all_frozen); @@ -463,8 +465,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, { BlockNumber nblocks, blkno, - total_index_blks, - *current_index_blks; + total_index_blks; HeapTupleData tuple; char *relname; BlockNumber empty_pages, @@ -512,15 +513,9 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, pgstat_progress_update_param(PROG_PAR_VAC_HEAP_BLKS, nblocks); /* total_index_blks */ - current_index_blks = (BlockNumber *) palloc(nindexes * sizeof(BlockNumber)); total_index_blks = 0; for (i = 0; i < nindexes; i++) - { - BlockNumber nblocks = RelationGetNumberOfBlocks(Irel[i]); - - current_index_blks[i] = nblocks; - total_index_blks += nblocks; - } + total_index_blks += RelationGetNumberOfBlocks(Irel[i]); pgstat_progress_update_param(PROG_PAR_VAC_IDX_BLKS, total_index_blks); /* @@ -657,16 +652,12 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, /* Remove index entries */ pgstat_progress_update_param(PROG_PAR_VAC_PHASE_ID, LV_PHASE_VACUUM_INDEX); + vacrelstats->index_blks_vacuumed = 0; /* reset for this round */ for (i = 0; i < nindexes; i++) - { lazy_vacuum_index(Irel[i], &indstats[i], vacrelstats); - pgstat_progress_update_param(PROG_PAR_VAC_IDX_BLKS_DONE, - current_index_blks[i]); - } - pgstat_progress_update_param(PROG_PAR_VAC_N_IDX_SCAN, vacrelstats->num_index_scans+1); @@ -1222,15 +1213,12 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, /* Remove index entries */ pgstat_progress_update_param(PROG_PAR_VAC_PHASE_ID, LV_PHASE_VACUUM_INDEX); + vacrelstats->index_blks_vacuumed = 0; /* reset for this round */ for (i = 0; i < nindexes; i++) - { lazy_vacuum_index(Irel[i], &indstats[i], vacrelstats); - pgstat_progress_update_param(PROG_PAR_VAC_IDX_BLKS_DONE, - current_index_blks[i]); - } pgstat_progress_update_param(PROG_PAR_VAC_N_IDX_SCAN, vacrelstats->num_index_scans + 1); @@ -1922,11 +1910,19 @@ lazy_record_dead_tuple(LVRelStats *vacrelstats, * Assumes dead_tuples array is in sorted order. */ static bool -lazy_tid_reaped(ItemPointer itemptr, void *state) +lazy_tid_reaped(ItemPointer itemptr, BlockNumber index_blkno, void *state) { LVRelStats *vacrelstats = (LVRelStats *) state; ItemPointer res; + if (index_blkno != vacrelstats->last_index_blkno) + { + ++vacrelstats->index_blks_vacuumed; + pgstat_progress_update_param(PROG_PAR_VAC_IDX_BLKS_DONE, + vacrelstats->index_blks_vacuumed); + vacrelstats->last_index_blkno = index_blkno; + } + res = (ItemPointer) bsearch((void *) itemptr, (void *) vacrelstats->dead_tuples, vacrelstats->num_dead_tuples, diff --git a/src/include/access/genam.h b/src/include/access/genam.h index 81907d5..8d67d1c 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -77,7 +77,9 @@ typedef struct IndexBulkDeleteResult } IndexBulkDeleteResult; /* Typedef for callback function to determine if a tuple is bulk-deletable */ -typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state); +typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, + BlockNumber index_blkno, + void *state); /* struct definitions appear in relscan.h */ typedef struct IndexScanDescData *IndexScanDesc; -- 1.7.1