Skip to content

Commit ccf193f

Browse files
committed
New-style vacuum neglected to update pg_class statistics about indexes
if there were no deletions to do.
1 parent 75586cb commit ccf193f

File tree

3 files changed

+128
-33
lines changed

3 files changed

+128
-33
lines changed

src/backend/commands/vacuum.c

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.205 2001/07/15 22:48:17 tgl Exp $
16+
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.206 2001/07/18 00:46:24 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -129,11 +129,11 @@ static void vacuum_index(VacPageList vacpagelist, Relation indrel,
129129
double num_tuples, int keep_tuples);
130130
static void scan_index(Relation indrel, double num_tuples);
131131
static bool tid_reaped(ItemPointer itemptr, void *state);
132+
static bool dummy_tid_reaped(ItemPointer itemptr, void *state);
132133
static void vac_update_fsm(Relation onerel, VacPageList fraged_pages,
133134
BlockNumber rel_pages);
134135
static VacPage copy_vac_page(VacPage vacpage);
135136
static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
136-
static bool is_partial_index(Relation indrel);
137137
static void *vac_bsearch(const void *key, const void *base,
138138
size_t nelem, size_t size,
139139
int (*compar) (const void *, const void *));
@@ -2178,51 +2178,52 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
21782178

21792179
/*
21802180
* scan_index() -- scan one index relation to update statistic.
2181+
*
2182+
* We use this when we have no deletions to do.
21812183
*/
21822184
static void
21832185
scan_index(Relation indrel, double num_tuples)
21842186
{
2185-
RetrieveIndexResult res;
2186-
IndexScanDesc iscan;
2187-
BlockNumber nipages;
2188-
double nitups;
2187+
IndexBulkDeleteResult *stats;
21892188
VacRUsage ru0;
21902189

21912190
vac_init_rusage(&ru0);
21922191

2193-
/* walk through the entire index */
2194-
iscan = index_beginscan(indrel, false, 0, (ScanKey) NULL);
2195-
nitups = 0;
2196-
2197-
while ((res = index_getnext(iscan, ForwardScanDirection))
2198-
!= (RetrieveIndexResult) NULL)
2199-
{
2200-
nitups += 1;
2201-
pfree(res);
2202-
}
2192+
/*
2193+
* Even though we're not planning to delete anything, use the
2194+
* ambulkdelete call, so that the scan happens within the index AM
2195+
* for more speed.
2196+
*/
2197+
stats = index_bulk_delete(indrel, dummy_tid_reaped, NULL);
22032198

2204-
index_endscan(iscan);
2199+
if (!stats)
2200+
return;
22052201

22062202
/* now update statistics in pg_class */
2207-
nipages = RelationGetNumberOfBlocks(indrel);
2208-
vac_update_relstats(RelationGetRelid(indrel), nipages, nitups, false);
2203+
vac_update_relstats(RelationGetRelid(indrel),
2204+
stats->num_pages, stats->num_index_tuples,
2205+
false);
22092206

22102207
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f.\n\t%s",
2211-
RelationGetRelationName(indrel), nipages, nitups,
2208+
RelationGetRelationName(indrel),
2209+
stats->num_pages, stats->num_index_tuples,
22122210
vac_show_rusage(&ru0));
22132211

22142212
/*
22152213
* Check for tuple count mismatch. If the index is partial, then
22162214
* it's OK for it to have fewer tuples than the heap; else we got trouble.
22172215
*/
2218-
if (nitups != num_tuples)
2216+
if (stats->num_index_tuples != num_tuples)
22192217
{
2220-
if (nitups > num_tuples ||
2221-
! is_partial_index(indrel))
2218+
if (stats->num_index_tuples > num_tuples ||
2219+
! vac_is_partial_index(indrel))
22222220
elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
22232221
\n\tRecreate the index.",
2224-
RelationGetRelationName(indrel), nitups, num_tuples);
2222+
RelationGetRelationName(indrel),
2223+
stats->num_index_tuples, num_tuples);
22252224
}
2225+
2226+
pfree(stats);
22262227
}
22272228

22282229
/*
@@ -2269,7 +2270,7 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
22692270
if (stats->num_index_tuples != num_tuples + keep_tuples)
22702271
{
22712272
if (stats->num_index_tuples > num_tuples + keep_tuples ||
2272-
! is_partial_index(indrel))
2273+
! vac_is_partial_index(indrel))
22732274
elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
22742275
\n\tRecreate the index.",
22752276
RelationGetRelationName(indrel),
@@ -2331,6 +2332,15 @@ tid_reaped(ItemPointer itemptr, void *state)
23312332
return true;
23322333
}
23332334

2335+
/*
2336+
* Dummy version for scan_index.
2337+
*/
2338+
static bool
2339+
dummy_tid_reaped(ItemPointer itemptr, void *state)
2340+
{
2341+
return false;
2342+
}
2343+
23342344
/*
23352345
* Update the shared Free Space Map with the info we now have about
23362346
* free space in the relation, discarding any old info the map may have.
@@ -2552,8 +2562,11 @@ vac_close_indexes(int nindexes, Relation *Irel)
25522562
}
25532563

25542564

2555-
static bool
2556-
is_partial_index(Relation indrel)
2565+
/*
2566+
* Is an index partial (ie, could it contain fewer tuples than the heap?)
2567+
*/
2568+
bool
2569+
vac_is_partial_index(Relation indrel)
25572570
{
25582571
bool result;
25592572
HeapTuple cachetuple;
@@ -2570,7 +2583,7 @@ is_partial_index(Relation indrel)
25702583
ObjectIdGetDatum(RelationGetRelid(indrel)),
25712584
0, 0, 0);
25722585
if (!HeapTupleIsValid(cachetuple))
2573-
elog(ERROR, "is_partial_index: index %u not found",
2586+
elog(ERROR, "vac_is_partial_index: index %u not found",
25742587
RelationGetRelid(indrel));
25752588
indexStruct = (Form_pg_index) GETSTRUCT(cachetuple);
25762589

src/backend/commands/vacuumlazy.c

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
*
3232
*
3333
* IDENTIFICATION
34-
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.2 2001/07/15 22:48:17 tgl Exp $
34+
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.3 2001/07/18 00:46:25 tgl Exp $
3535
*
3636
*-------------------------------------------------------------------------
3737
*/
@@ -101,6 +101,7 @@ static TransactionId XmaxRecent;
101101
static void lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
102102
Relation *Irel, int nindexes);
103103
static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats);
104+
static void lazy_scan_index(Relation indrel, LVRelStats *vacrelstats);
104105
static void lazy_vacuum_index(Relation indrel, LVRelStats *vacrelstats);
105106
static int lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
106107
int tupindex, LVRelStats *vacrelstats);
@@ -113,6 +114,7 @@ static void lazy_record_dead_tuple(LVRelStats *vacrelstats,
113114
static void lazy_record_free_space(LVRelStats *vacrelstats,
114115
BlockNumber page, Size avail);
115116
static bool lazy_tid_reaped(ItemPointer itemptr, void *state);
117+
static bool dummy_tid_reaped(ItemPointer itemptr, void *state);
116118
static void lazy_update_fsm(Relation onerel, LVRelStats *vacrelstats);
117119
static int vac_cmp_itemptr(const void *left, const void *right);
118120

@@ -197,6 +199,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
197199
tups_vacuumed,
198200
nkeep,
199201
nunused;
202+
bool did_vacuum_index = false;
200203
int i;
201204
VacRUsage ru0;
202205

@@ -235,6 +238,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
235238
/* Remove index entries */
236239
for (i = 0; i < nindexes; i++)
237240
lazy_vacuum_index(Irel[i], vacrelstats);
241+
did_vacuum_index = true;
238242
/* Remove tuples from heap */
239243
lazy_vacuum_heap(onerel, vacrelstats);
240244
/* Forget the now-vacuumed tuples, and press on */
@@ -378,6 +382,9 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
378382
ReleaseBuffer(buf);
379383
}
380384

385+
/* save stats for use later */
386+
vacrelstats->rel_tuples = num_tuples;
387+
381388
/* If any tuples need to be deleted, perform final vacuum cycle */
382389
/* XXX put a threshold on min nuber of tuples here? */
383390
if (vacrelstats->num_dead_tuples > 0)
@@ -388,9 +395,12 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
388395
/* Remove tuples from heap */
389396
lazy_vacuum_heap(onerel, vacrelstats);
390397
}
391-
392-
/* save stats for use later */
393-
vacrelstats->rel_tuples = num_tuples;
398+
else if (! did_vacuum_index)
399+
{
400+
/* Scan indexes just to update pg_class statistics about them */
401+
for (i = 0; i < nindexes; i++)
402+
lazy_scan_index(Irel[i], vacrelstats);
403+
}
394404

395405
elog(MESSAGE_LEVEL, "Pages %u: Changed %u, Empty %u; \
396406
Tup %.0f: Vac %.0f, Keep %.0f, UnUsed %.0f.\n\tTotal %s",
@@ -495,6 +505,68 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
495505
return tupindex;
496506
}
497507

508+
/*
509+
* lazy_scan_index() -- scan one index relation to update pg_class statistic.
510+
*
511+
* We use this when we have no deletions to do.
512+
*/
513+
static void
514+
lazy_scan_index(Relation indrel, LVRelStats *vacrelstats)
515+
{
516+
IndexBulkDeleteResult *stats;
517+
VacRUsage ru0;
518+
519+
vac_init_rusage(&ru0);
520+
521+
/*
522+
* If the index is not partial, skip the scan, and just assume it
523+
* has the same number of tuples as the heap.
524+
*/
525+
if (! vac_is_partial_index(indrel))
526+
{
527+
vac_update_relstats(RelationGetRelid(indrel),
528+
RelationGetNumberOfBlocks(indrel),
529+
vacrelstats->rel_tuples,
530+
false);
531+
return;
532+
}
533+
534+
/*
535+
* If index is unsafe for concurrent access, must lock it;
536+
* but a shared lock should be sufficient.
537+
*/
538+
if (! indrel->rd_am->amconcurrent)
539+
LockRelation(indrel, AccessShareLock);
540+
541+
/*
542+
* Even though we're not planning to delete anything, use the
543+
* ambulkdelete call, so that the scan happens within the index AM
544+
* for more speed.
545+
*/
546+
stats = index_bulk_delete(indrel, dummy_tid_reaped, NULL);
547+
548+
/*
549+
* Release lock acquired above.
550+
*/
551+
if (! indrel->rd_am->amconcurrent)
552+
UnlockRelation(indrel, AccessShareLock);
553+
554+
if (!stats)
555+
return;
556+
557+
/* now update statistics in pg_class */
558+
vac_update_relstats(RelationGetRelid(indrel),
559+
stats->num_pages, stats->num_index_tuples,
560+
false);
561+
562+
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f.\n\t%s",
563+
RelationGetRelationName(indrel),
564+
stats->num_pages, stats->num_index_tuples,
565+
vac_show_rusage(&ru0));
566+
567+
pfree(stats);
568+
}
569+
498570
/*
499571
* lazy_vacuum_index() -- vacuum one index relation.
500572
*
@@ -955,6 +1027,15 @@ lazy_tid_reaped(ItemPointer itemptr, void *state)
9551027
return (res != NULL);
9561028
}
9571029

1030+
/*
1031+
* Dummy version for lazy_scan_index.
1032+
*/
1033+
static bool
1034+
dummy_tid_reaped(ItemPointer itemptr, void *state)
1035+
{
1036+
return false;
1037+
}
1038+
9581039
/*
9591040
* Update the shared Free Space Map with the info we now have about
9601041
* free space in the relation, discarding any old info the map may have.

src/include/commands/vacuum.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: vacuum.h,v 1.38 2001/07/13 22:55:59 tgl Exp $
10+
* $Id: vacuum.h,v 1.39 2001/07/18 00:46:25 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -44,6 +44,7 @@ extern void vac_update_relstats(Oid relid,
4444
BlockNumber num_pages,
4545
double num_tuples,
4646
bool hasindex);
47+
extern bool vac_is_partial_index(Relation indrel);
4748
extern void vac_init_rusage(VacRUsage *ru0);
4849
extern const char *vac_show_rusage(VacRUsage *ru0);
4950

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy