postgres.git / summary / log / commit / refs

commit    81b9b5ce490a645bde8df203ec4a3b2903d88f31
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Fri Mar 02 16:22:42 2018 +0000
First released in: 11.0, 9.3.23, 9.4.18, 9.5.13, 9.6.9, 10.4

    Make gistvacuumcleanup() count the actual number of index tuples.
    
    Previously, it just returned the heap tuple count, which might be only an
    estimate, and would be completely the wrong thing if the index is partial.
    Since this function scans every index page anyway to find free pages,
    it's practically free to count the surviving index tuples.  Let's do that
    and return an accurate count.
    
    This is easily visible as a wrong reltuples value for a partial GiST
    index following VACUUM, so back-patch to all supported branches.
    
    Andrey Borodin, reviewed by Michail Nikolaev
    
    Discussion: https://postgr.es/m/151956654251.6915.675951950408204404.pgcf@coridan.postgresql.org


src/backend/access/gist/gistvacuum.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c index 22181c6299b..5948218c779 100644 --- a/src/backend/access/gist/gistvacuum.c +++ b/src/backend/access/gist/gistvacuum.c @@ -32,6 +32,7 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) BlockNumber npages, blkno; BlockNumber totFreePages; + double tuplesCount; bool needLock; /* No-op in ANALYZE ONLY mode */ @@ -40,17 +41,7 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) /* Set up all-zero stats if gistbulkdelete wasn't called */ if (stats == NULL) - { stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult)); - /* use heap's tuple count */ - stats->num_index_tuples = info->num_heap_tuples; - stats->estimated_count = info->estimated_count; - - /* - * XXX the above is wrong if index is partial. Would it be OK to just - * return NULL, or is there work we must do below? - */ - } /* * Need lock unless it's local to this backend. @@ -65,6 +56,7 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) UnlockRelationForExtension(rel, ExclusiveLock); totFreePages = 0; + tuplesCount = 0; for (blkno = GIST_ROOT_BLKNO + 1; blkno < npages; blkno++) { Buffer buffer; @@ -82,6 +74,11 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) totFreePages++; RecordFreeIndexPage(rel, blkno); } + else if (GistPageIsLeaf(page)) + { + /* count tuples in index (considering only leaf tuples) */ + tuplesCount += PageGetMaxOffsetNumber(page); + } UnlockReleaseBuffer(buffer); } @@ -95,6 +92,8 @@ gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) stats->num_pages = RelationGetNumberOfBlocks(rel); if (needLock) UnlockRelationForExtension(rel, ExclusiveLock); + stats->num_index_tuples = tuplesCount; + stats->estimated_count = false; return stats; } [parent: 7240962f8626]