Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdcf8409

Browse files
committed
Don't reset pg_class.reltuples and relpages in VACUUM, if any pages were
skipped. We could update relpages anyway, but it seems better to onlyupdate it together with reltuples, because we use the reltuples/relpagesratio in the planner. Also don't update n_live_tuples in pgstat.ANALYZE in VACUUM ANALYZE now needs to update pg_class, if theVACUUM-phase didn't do so. Added some boolean-passing to let analyze_relknow if it should update pg_class or not.I also moved the relcache invalidation (to update rd_targblock) fromvac_update_relstats to where RelationTruncate is called, becausevac_update_relstats is not called for partial vacuums anymore. It's moreobvious to send the invalidation close to the truncation that requires it.Per report by Ned T. Crigler.
1 parent5a90bc1 commitdcf8409

File tree

7 files changed

+94
-61
lines changed

7 files changed

+94
-61
lines changed

‎src/backend/commands/analyze.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.129 2008/12/13 19:13:44 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.130 2008/12/17 09:15:02 heikki Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -101,10 +101,18 @@ static bool std_typanalyze(VacAttrStats *stats);
101101

102102
/*
103103
*analyze_rel() -- analyze one relation
104+
*
105+
* If update_reltuples is true, we update reltuples and relpages columns
106+
* in pg_class. Caller should pass false if we're part of VACUUM ANALYZE,
107+
* and the VACUUM didn't skip any pages. We only have an approximate count,
108+
* so we don't want to overwrite the accurate values already inserted by the
109+
* VACUUM in that case. VACUUM always scans all indexes, however, so the
110+
* pg_class entries for indexes are never updated if we're part of VACUUM
111+
* ANALYZE.
104112
*/
105113
void
106114
analyze_rel(Oidrelid,VacuumStmt*vacstmt,
107-
BufferAccessStrategybstrategy)
115+
BufferAccessStrategybstrategy,boolupdate_reltuples)
108116
{
109117
Relationonerel;
110118
intattr_cnt,
@@ -364,7 +372,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
364372
* autovacuum code doesn't go nuts trying to get stats about a
365373
* zero-column table.
366374
*/
367-
if (!vacstmt->vacuum)
375+
if (update_reltuples)
368376
pgstat_report_analyze(onerel,0,0);
369377
gotocleanup;
370378
}
@@ -455,18 +463,24 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
455463
}
456464

457465
/*
458-
* If we are running a standalone ANALYZE, update pages/tuples stats in
459-
* pg_class. We know the accurate page count from the smgr, but only an
460-
* approximate number of tuples; therefore, if we are part of VACUUM
461-
* ANALYZE do *not* overwrite the accurate count already inserted by
462-
* VACUUM.The same consideration applies to indexes.
466+
* Update pages/tuples stats in pg_class.
463467
*/
464-
if (!vacstmt->vacuum)
468+
if (update_reltuples)
465469
{
466470
vac_update_relstats(onerel,
467471
RelationGetNumberOfBlocks(onerel),
468472
totalrows,hasindex,InvalidTransactionId);
473+
/* report results to the stats collector, too */
474+
pgstat_report_analyze(onerel,totalrows,totaldeadrows);
475+
}
469476

477+
/*
478+
* Same for indexes. Vacuum always scans all indexes, so if we're part of
479+
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by
480+
* VACUUM.
481+
*/
482+
if (!vacstmt->vacuum)
483+
{
470484
for (ind=0;ind<nindexes;ind++)
471485
{
472486
AnlIndexData*thisdata=&indexdata[ind];
@@ -477,9 +491,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
477491
RelationGetNumberOfBlocks(Irel[ind]),
478492
totalindexrows, false,InvalidTransactionId);
479493
}
480-
481-
/* report results to the stats collector, too */
482-
pgstat_report_analyze(onerel,totalrows,totaldeadrows);
483494
}
484495

485496
/* We skip to here if there were no analyzable columns */

‎src/backend/commands/vacuum.c

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.382 2008/12/03 13:05:22 heikki Exp $
16+
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.383 2008/12/17 09:15:02 heikki Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -216,7 +216,7 @@ static List *get_rel_oids(Oid relid, const RangeVar *vacrel,
216216
constchar*stmttype);
217217
staticvoidvac_truncate_clog(TransactionIdfrozenXID);
218218
staticvoidvacuum_rel(Oidrelid,VacuumStmt*vacstmt,booldo_toast,
219-
boolfor_wraparound);
219+
boolfor_wraparound,bool*scanned_all);
220220
staticvoidfull_vacuum_rel(Relationonerel,VacuumStmt*vacstmt);
221221
staticvoidscan_heap(VRelStats*vacrelstats,Relationonerel,
222222
VacPageListvacuum_pages,VacPageListfraged_pages);
@@ -436,9 +436,11 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
436436
foreach(cur,relations)
437437
{
438438
Oidrelid=lfirst_oid(cur);
439+
boolscanned_all= false;
439440

440441
if (vacstmt->vacuum)
441-
vacuum_rel(relid,vacstmt,do_toast,for_wraparound);
442+
vacuum_rel(relid,vacstmt,do_toast,for_wraparound,
443+
&scanned_all);
442444

443445
if (vacstmt->analyze)
444446
{
@@ -460,7 +462,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
460462
else
461463
old_context=MemoryContextSwitchTo(anl_context);
462464

463-
analyze_rel(relid,vacstmt,vac_strategy);
465+
analyze_rel(relid,vacstmt,vac_strategy, !scanned_all);
464466

465467
if (use_own_xacts)
466468
{
@@ -756,21 +758,9 @@ vac_update_relstats(Relation relation,
756758
dirty= true;
757759
}
758760

759-
/*
760-
* If anything changed, write out the tuple. Even if nothing changed,
761-
* force relcache invalidation so all backends reset their rd_targblock
762-
* --- otherwise it might point to a page we truncated away.
763-
*/
761+
/* If anything changed, write out the tuple. */
764762
if (dirty)
765-
{
766763
heap_inplace_update(rd,ctup);
767-
/* the above sends a cache inval message */
768-
}
769-
else
770-
{
771-
/* no need to change tuple, but force relcache inval anyway */
772-
CacheInvalidateRelcacheByTuple(ctup);
773-
}
774764

775765
heap_close(rd,RowExclusiveLock);
776766
}
@@ -986,10 +976,14 @@ vac_truncate_clog(TransactionId frozenXID)
986976
*many small transactions. Otherwise, two-phase locking would require
987977
*us to lock the entire database during one pass of the vacuum cleaner.
988978
*
979+
*We'll return true in *scanned_all if the vacuum scanned all heap
980+
*pages, and updated pg_class.
981+
*
989982
*At entry and exit, we are not inside a transaction.
990983
*/
991984
staticvoid
992-
vacuum_rel(Oidrelid,VacuumStmt*vacstmt,booldo_toast,boolfor_wraparound)
985+
vacuum_rel(Oidrelid,VacuumStmt*vacstmt,booldo_toast,boolfor_wraparound,
986+
bool*scanned_all)
993987
{
994988
LOCKMODElmode;
995989
Relationonerel;
@@ -998,6 +992,9 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
998992
Oidsave_userid;
999993
boolsave_secdefcxt;
1000994

995+
if (scanned_all)
996+
*scanned_all= false;
997+
1001998
/* Begin a transaction for vacuuming this relation */
1002999
StartTransactionCommand();
10031000

@@ -1162,7 +1159,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
11621159
if (vacstmt->full)
11631160
full_vacuum_rel(onerel,vacstmt);
11641161
else
1165-
lazy_vacuum_rel(onerel,vacstmt,vac_strategy);
1162+
lazy_vacuum_rel(onerel,vacstmt,vac_strategy,scanned_all);
11661163

11671164
/* Restore userid */
11681165
SetUserIdAndContext(save_userid,save_secdefcxt);
@@ -1184,7 +1181,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
11841181
* totally unimportant for toast relations.
11851182
*/
11861183
if (toast_relid!=InvalidOid)
1187-
vacuum_rel(toast_relid,vacstmt, false,for_wraparound);
1184+
vacuum_rel(toast_relid,vacstmt, false,for_wraparound,NULL);
11881185

11891186
/*
11901187
* Now release the session-level lock on the master table.
@@ -1296,7 +1293,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
12961293

12971294
/* report results to the stats collector, too */
12981295
pgstat_report_vacuum(RelationGetRelid(onerel),onerel->rd_rel->relisshared,
1299-
vacstmt->analyze,vacrelstats->rel_tuples);
1296+
true,vacstmt->analyze,vacrelstats->rel_tuples);
13001297
}
13011298

13021299

@@ -2866,6 +2863,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
28662863
if (blkno<nblocks)
28672864
{
28682865
RelationTruncate(onerel,blkno);
2866+
2867+
/* force relcache inval so all backends reset their rd_targblock */
2868+
CacheInvalidateRelcache(onerel);
2869+
28692870
vacrelstats->rel_pages=blkno;/* set new number of blocks */
28702871
}
28712872

@@ -3286,6 +3287,10 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
32863287
RelationGetRelationName(onerel),
32873288
vacrelstats->rel_pages,relblocks)));
32883289
RelationTruncate(onerel,relblocks);
3290+
3291+
/* force relcache inval so all backends reset their rd_targblock */
3292+
CacheInvalidateRelcache(onerel);
3293+
32893294
vacrelstats->rel_pages=relblocks;/* set new number of blocks */
32903295
}
32913296
}

‎src/backend/commands/vacuumlazy.c

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
*
3030
*
3131
* IDENTIFICATION
32-
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.113 2008/12/04 11:42:23 heikki Exp $
32+
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.114 2008/12/17 09:15:02 heikki Exp $
3333
*
3434
*-------------------------------------------------------------------------
3535
*/
@@ -50,6 +50,7 @@
5050
#include"storage/bufmgr.h"
5151
#include"storage/freespace.h"
5252
#include"storage/lmgr.h"
53+
#include"utils/inval.h"
5354
#include"utils/lsyscache.h"
5455
#include"utils/memutils.h"
5556
#include"utils/pg_rusage.h"
@@ -135,7 +136,7 @@ static intvac_cmp_itemptr(const void *left, const void *right);
135136
*/
136137
void
137138
lazy_vacuum_rel(Relationonerel,VacuumStmt*vacstmt,
138-
BufferAccessStrategybstrategy)
139+
BufferAccessStrategybstrategy,bool*scanned_all)
139140
{
140141
LVRelStats*vacrelstats;
141142
Relation*Irel;
@@ -163,7 +164,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
163164
vacrelstats= (LVRelStats*)palloc0(sizeof(LVRelStats));
164165

165166
vacrelstats->num_index_scans=0;
166-
vacrelstats->scanned_all= true;
167+
vacrelstats->scanned_all= true;/* will be cleared if we skip a page */
167168

168169
/* Open all indexes of the relation */
169170
vac_open_indexes(onerel,RowExclusiveLock,&nindexes,&Irel);
@@ -190,16 +191,23 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
190191
FreeSpaceMapVacuum(onerel);
191192

192193
/*
193-
* Update statistics in pg_class. We can only advance relfrozenxid if we
194-
* didn't skip any pages.
194+
* Update statistics in pg_class. But only if we didn't skip any pages;
195+
* the tuple count only includes tuples from the pages we've visited, and
196+
* we haven't frozen tuples in unvisited pages either. The page count is
197+
* accurate in any case, but because we use the reltuples / relpages
198+
* ratio in the planner, it's better to not update relpages either if we
199+
* can't update reltuples.
195200
*/
196-
vac_update_relstats(onerel,
197-
vacrelstats->rel_pages,vacrelstats->rel_tuples,
198-
vacrelstats->hasindex,
199-
vacrelstats->scanned_all ?FreezeLimit :InvalidOid);
201+
if (vacrelstats->scanned_all)
202+
vac_update_relstats(onerel,
203+
vacrelstats->rel_pages,vacrelstats->rel_tuples,
204+
vacrelstats->hasindex,
205+
FreezeLimit);
200206

201207
/* report results to the stats collector, too */
202-
pgstat_report_vacuum(RelationGetRelid(onerel),onerel->rd_rel->relisshared,
208+
pgstat_report_vacuum(RelationGetRelid(onerel),
209+
onerel->rd_rel->relisshared,
210+
vacrelstats->scanned_all,
203211
vacstmt->analyze,vacrelstats->rel_tuples);
204212

205213
/* and log the action if appropriate */
@@ -221,6 +229,9 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
221229
vacrelstats->tuples_deleted,vacrelstats->rel_tuples,
222230
pg_rusage_show(&ru0))));
223231
}
232+
233+
if (scanned_all)
234+
*scanned_all=vacrelstats->scanned_all;
224235
}
225236

226237

@@ -952,12 +963,14 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
952963
*/
953964
RelationTruncate(onerel,new_rel_pages);
954965

966+
/* force relcache inval so all backends reset their rd_targblock */
967+
CacheInvalidateRelcache(onerel);
968+
955969
/*
956970
* Note: once we have truncated, we *must* keep the exclusive lock until
957-
* commit.The sinval message that will be sent at commit (as a result of
958-
* vac_update_relstats()) must be received by other backends, to cause
959-
* them to reset their rd_targblock values, before they can safely access
960-
* the table again.
971+
* commit.The sinval message won't be sent until commit, and other
972+
* backends must see it and reset their rd_targblock values before they
973+
* can safely access the table again.
961974
*/
962975

963976
/* update statistics */

‎src/backend/parser/gram.y

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.643 2008/12/04 17:51:26 petere Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.644 2008/12/17 09:15:02 heikki Exp $
1515
*
1616
* HISTORY
1717
* AUTHORDATEMAJOR EVENT
@@ -5875,7 +5875,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
58755875
n->analyze =false;
58765876
n->full =$2;
58775877
n->freeze_min_age =$3 ?0 : -1;
5878-
n->scan_all =$3;
5878+
n->scan_all =$2 ||$3;
58795879
n->verbose =$4;
58805880
n->relation =NULL;
58815881
n->va_cols = NIL;
@@ -5888,7 +5888,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
58885888
n->analyze =false;
58895889
n->full =$2;
58905890
n->freeze_min_age =$3 ?0 : -1;
5891-
n->scan_all =$3;
5891+
n->scan_all =$2 ||$3;
58925892
n->verbose =$4;
58935893
n->relation =$5;
58945894
n->va_cols = NIL;
@@ -5900,7 +5900,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
59005900
n->vacuum =true;
59015901
n->full =$2;
59025902
n->freeze_min_age =$3 ?0 : -1;
5903-
n->scan_all =$3;
5903+
n->scan_all =$2 ||$3;
59045904
n->verbose |=$4;
59055905
$$ = (Node *)n;
59065906
}

‎src/backend/postmaster/pgstat.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*Copyright (c) 2001-2008, PostgreSQL Global Development Group
1515
*
16-
*$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.185 2008/12/0815:44:54 tgl Exp $
16+
*$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.186 2008/12/17 09:15:03 heikki Exp $
1717
* ----------
1818
*/
1919
#include"postgres.h"
@@ -1178,7 +1178,7 @@ pgstat_report_autovac(Oid dboid)
11781178
* ---------
11791179
*/
11801180
void
1181-
pgstat_report_vacuum(Oidtableoid,boolshared,
1181+
pgstat_report_vacuum(Oidtableoid,boolshared,boolscanned_all,
11821182
boolanalyze,PgStat_Countertuples)
11831183
{
11841184
PgStat_MsgVacuummsg;
@@ -1189,6 +1189,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
11891189
pgstat_setheader(&msg.m_hdr,PGSTAT_MTYPE_VACUUM);
11901190
msg.m_databaseid=shared ?InvalidOid :MyDatabaseId;
11911191
msg.m_tableoid=tableoid;
1192+
msg.m_scanned_all=scanned_all;
11921193
msg.m_analyze=analyze;
11931194
msg.m_autovacuum=IsAutoVacuumWorkerProcess();/* is this autovacuum? */
11941195
msg.m_vacuumtime=GetCurrentTimestamp();
@@ -3765,12 +3766,14 @@ pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len)
37653766
tabentry->autovac_vacuum_timestamp=msg->m_vacuumtime;
37663767
else
37673768
tabentry->vacuum_timestamp=msg->m_vacuumtime;
3768-
tabentry->n_live_tuples=msg->m_tuples;
3769+
if (msg->m_scanned_all)
3770+
tabentry->n_live_tuples=msg->m_tuples;
37693771
/* Resetting dead_tuples to 0 is an approximation ... */
37703772
tabentry->n_dead_tuples=0;
37713773
if (msg->m_analyze)
37723774
{
3773-
tabentry->last_anl_tuples=msg->m_tuples;
3775+
if (msg->m_scanned_all)
3776+
tabentry->last_anl_tuples=msg->m_tuples;
37743777
if (msg->m_autovacuum)
37753778
tabentry->autovac_analyze_timestamp=msg->m_vacuumtime;
37763779
else
@@ -3780,7 +3783,7 @@ pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len)
37803783
{
37813784
/* last_anl_tuples must never exceed n_live_tuples+n_dead_tuples */
37823785
tabentry->last_anl_tuples=Min(tabentry->last_anl_tuples,
3783-
msg->m_tuples);
3786+
tabentry->n_live_tuples);
37843787
}
37853788
}
37863789

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp