postgres.git / summary / log / commit / refs

commit    dcc20946a8fc192a71cedcaae25c996973747ff5
Author:   Fujii Masao <fujii@postgresql.org>
Date:     Fri Nov 27 11:16:44 2020 +0000
First released in: 14.0, 12.6, 13.2

    Fix CLUSTER progress reporting of number of blocks scanned.
    
    Previously pg_stat_progress_cluster view reported the current block
    number in heap scan as the number of heap blocks scanned (i.e.,
    heap_blks_scanned). This reported number could be incorrect when
    synchronize_seqscans is enabled, because it allowed the heap scan to
    start at block in middle. This could result in wraparounds in the
    heap_blks_scanned column when the heap scan wrapped around.
    This commit fixes the bug by calculating the number of blocks from
    the block that the heap scan starts at to the current block in scan,
    and reporting that number in the heap_blks_scanned column.
    
    Also, in pg_stat_progress_cluster view, previously heap_blks_scanned
    could not reach heap_blks_total at the end of heap scan phase
    if the last pages scanned were empty. This commit fixes the bug by
    manually updating heap_blks_scanned to the same value as
    heap_blks_total when the heap scan phase finishes.
    
    Back-patch to v12 where pg_stat_progress_cluster view was introduced.
    
    Reported-by: Matthias van de Meent
    Author: Matthias van de Meent
    Reviewed-by: Fujii Masao
    Discussion: https://postgr.es/m/CAEze2WjCBWSGkVfYag001Rc4+-nNLDpWM7QbyD6yPvuhKs-gYQ@mail.gmail.com


src/backend/access/heap/heapam_handler.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 9d282886492..d1e0d53e6e4 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -696,6 +696,7 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap, Datum *values; bool *isnull; BufferHeapTupleTableSlot *hslot; + BlockNumber prev_cblock = InvalidBlockNumber; /* Remember if it's a system catalog */ is_system_catalog = IsSystemRelation(OldHeap); @@ -791,14 +792,38 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap, else { if (!table_scan_getnextslot(tableScan, ForwardScanDirection, slot)) + { + /* + * If the last pages of the scan were empty, we would go to + * the next phase while heap_blks_scanned != heap_blks_total. + * Instead, to ensure that heap_blks_scanned is equivalent to + * total_heap_blks after the table scan phase, this parameter + * is manually updated to the correct value when the table + * scan finishes. + */ + pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_BLKS_SCANNED, + heapScan->rs_nblocks); break; + } /* * In scan-and-sort mode and also VACUUM FULL, set heap blocks * scanned + * + * Note that heapScan may start at an offset and wrap around, i.e. + * rs_startblock may be >0, and rs_cblock may end with a number + * below rs_startblock. To prevent showing this wraparound to the + * user, we offset rs_cblock by rs_startblock (modulo rs_nblocks). */ - pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_BLKS_SCANNED, - heapScan->rs_cblock + 1); + if (prev_cblock != heapScan->rs_cblock) + { + pgstat_progress_update_param(PROGRESS_CLUSTER_HEAP_BLKS_SCANNED, + (heapScan->rs_cblock + + heapScan->rs_nblocks - + heapScan->rs_startblock + ) % heapScan->rs_nblocks + 1); + prev_cblock = heapScan->rs_cblock; + } } tuple = ExecFetchSlotHeapTuple(slot, false, NULL); [parent: a0ef0817204d]