Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+41-28
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

+85-4
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

+2-1
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)