aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/analyze.c35
-rw-r--r--src/backend/commands/vacuum.c47
-rw-r--r--src/backend/commands/vacuumlazy.c41
-rw-r--r--src/backend/parser/gram.y8
-rw-r--r--src/backend/postmaster/pgstat.c13
-rw-r--r--src/include/commands/vacuum.h6
-rw-r--r--src/include/pgstat.h5
7 files changed, 94 insertions, 61 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 2b3af54ff05..a636720f110 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.129 2008/12/13 19:13:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.130 2008/12/17 09:15:02 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -101,10 +101,18 @@ static bool std_typanalyze(VacAttrStats *stats);
/*
* analyze_rel() -- analyze one relation
+ *
+ * If update_reltuples is true, we update reltuples and relpages columns
+ * in pg_class. Caller should pass false if we're part of VACUUM ANALYZE,
+ * and the VACUUM didn't skip any pages. We only have an approximate count,
+ * so we don't want to overwrite the accurate values already inserted by the
+ * VACUUM in that case. VACUUM always scans all indexes, however, so the
+ * pg_class entries for indexes are never updated if we're part of VACUUM
+ * ANALYZE.
*/
void
analyze_rel(Oid relid, VacuumStmt *vacstmt,
- BufferAccessStrategy bstrategy)
+ BufferAccessStrategy bstrategy, bool update_reltuples)
{
Relation onerel;
int attr_cnt,
@@ -364,7 +372,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
* autovacuum code doesn't go nuts trying to get stats about a
* zero-column table.
*/
- if (!vacstmt->vacuum)
+ if (update_reltuples)
pgstat_report_analyze(onerel, 0, 0);
goto cleanup;
}
@@ -455,18 +463,24 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
}
/*
- * If we are running a standalone ANALYZE, update pages/tuples stats in
- * pg_class. We know the accurate page count from the smgr, but only an
- * approximate number of tuples; therefore, if we are part of VACUUM
- * ANALYZE do *not* overwrite the accurate count already inserted by
- * VACUUM. The same consideration applies to indexes.
+ * Update pages/tuples stats in pg_class.
*/
- if (!vacstmt->vacuum)
+ if (update_reltuples)
{
vac_update_relstats(onerel,
RelationGetNumberOfBlocks(onerel),
totalrows, hasindex, InvalidTransactionId);
+ /* report results to the stats collector, too */
+ pgstat_report_analyze(onerel, totalrows, totaldeadrows);
+ }
+ /*
+ * Same for indexes. Vacuum always scans all indexes, so if we're part of
+ * VACUUM ANALYZE, don't overwrite the accurate count already inserted by
+ * VACUUM.
+ */
+ if (!vacstmt->vacuum)
+ {
for (ind = 0; ind < nindexes; ind++)
{
AnlIndexData *thisdata = &indexdata[ind];
@@ -477,9 +491,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
RelationGetNumberOfBlocks(Irel[ind]),
totalindexrows, false, InvalidTransactionId);
}
-
- /* report results to the stats collector, too */
- pgstat_report_analyze(onerel, totalrows, totaldeadrows);
}
/* We skip to here if there were no analyzable columns */
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index e016ddb067d..d6daca9e110 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.382 2008/12/03 13:05:22 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.383 2008/12/17 09:15:02 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -216,7 +216,7 @@ static List *get_rel_oids(Oid relid, const RangeVar *vacrel,
const char *stmttype);
static void vac_truncate_clog(TransactionId frozenXID);
static void vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast,
- bool for_wraparound);
+ bool for_wraparound, bool *scanned_all);
static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
static void scan_heap(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages);
@@ -436,9 +436,11 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
foreach(cur, relations)
{
Oid relid = lfirst_oid(cur);
+ bool scanned_all = false;
if (vacstmt->vacuum)
- vacuum_rel(relid, vacstmt, do_toast, for_wraparound);
+ vacuum_rel(relid, vacstmt, do_toast, for_wraparound,
+ &scanned_all);
if (vacstmt->analyze)
{
@@ -460,7 +462,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
else
old_context = MemoryContextSwitchTo(anl_context);
- analyze_rel(relid, vacstmt, vac_strategy);
+ analyze_rel(relid, vacstmt, vac_strategy, !scanned_all);
if (use_own_xacts)
{
@@ -756,21 +758,9 @@ vac_update_relstats(Relation relation,
dirty = true;
}
- /*
- * If anything changed, write out the tuple. Even if nothing changed,
- * force relcache invalidation so all backends reset their rd_targblock
- * --- otherwise it might point to a page we truncated away.
- */
+ /* If anything changed, write out the tuple. */
if (dirty)
- {
heap_inplace_update(rd, ctup);
- /* the above sends a cache inval message */
- }
- else
- {
- /* no need to change tuple, but force relcache inval anyway */
- CacheInvalidateRelcacheByTuple(ctup);
- }
heap_close(rd, RowExclusiveLock);
}
@@ -986,10 +976,14 @@ vac_truncate_clog(TransactionId frozenXID)
* many small transactions. Otherwise, two-phase locking would require
* us to lock the entire database during one pass of the vacuum cleaner.
*
+ * We'll return true in *scanned_all if the vacuum scanned all heap
+ * pages, and updated pg_class.
+ *
* At entry and exit, we are not inside a transaction.
*/
static void
-vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
+vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
+ bool *scanned_all)
{
LOCKMODE lmode;
Relation onerel;
@@ -998,6 +992,9 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
Oid save_userid;
bool save_secdefcxt;
+ if (scanned_all)
+ *scanned_all = false;
+
/* Begin a transaction for vacuuming this relation */
StartTransactionCommand();
@@ -1162,7 +1159,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
if (vacstmt->full)
full_vacuum_rel(onerel, vacstmt);
else
- lazy_vacuum_rel(onerel, vacstmt, vac_strategy);
+ lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all);
/* Restore userid */
SetUserIdAndContext(save_userid, save_secdefcxt);
@@ -1184,7 +1181,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
* totally unimportant for toast relations.
*/
if (toast_relid != InvalidOid)
- vacuum_rel(toast_relid, vacstmt, false, for_wraparound);
+ vacuum_rel(toast_relid, vacstmt, false, for_wraparound, NULL);
/*
* Now release the session-level lock on the master table.
@@ -1296,7 +1293,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
/* report results to the stats collector, too */
pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared,
- vacstmt->analyze, vacrelstats->rel_tuples);
+ true, vacstmt->analyze, vacrelstats->rel_tuples);
}
@@ -2866,6 +2863,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
if (blkno < nblocks)
{
RelationTruncate(onerel, blkno);
+
+ /* force relcache inval so all backends reset their rd_targblock */
+ CacheInvalidateRelcache(onerel);
+
vacrelstats->rel_pages = blkno; /* set new number of blocks */
}
@@ -3286,6 +3287,10 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
RelationGetRelationName(onerel),
vacrelstats->rel_pages, relblocks)));
RelationTruncate(onerel, relblocks);
+
+ /* force relcache inval so all backends reset their rd_targblock */
+ CacheInvalidateRelcache(onerel);
+
vacrelstats->rel_pages = relblocks; /* set new number of blocks */
}
}
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index b661fe39802..48da3209151 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -29,7 +29,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.113 2008/12/04 11:42:23 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.114 2008/12/17 09:15:02 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -50,6 +50,7 @@
#include "storage/bufmgr.h"
#include "storage/freespace.h"
#include "storage/lmgr.h"
+#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/pg_rusage.h"
@@ -135,7 +136,7 @@ static int vac_cmp_itemptr(const void *left, const void *right);
*/
void
lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
- BufferAccessStrategy bstrategy)
+ BufferAccessStrategy bstrategy, bool *scanned_all)
{
LVRelStats *vacrelstats;
Relation *Irel;
@@ -163,7 +164,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats));
vacrelstats->num_index_scans = 0;
- vacrelstats->scanned_all = true;
+ vacrelstats->scanned_all = true; /* will be cleared if we skip a page */
/* Open all indexes of the relation */
vac_open_indexes(onerel, RowExclusiveLock, &nindexes, &Irel);
@@ -190,16 +191,23 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
FreeSpaceMapVacuum(onerel);
/*
- * Update statistics in pg_class. We can only advance relfrozenxid if we
- * didn't skip any pages.
+ * Update statistics in pg_class. But only if we didn't skip any pages;
+ * the tuple count only includes tuples from the pages we've visited, and
+ * we haven't frozen tuples in unvisited pages either. The page count is
+ * accurate in any case, but because we use the reltuples / relpages
+ * ratio in the planner, it's better to not update relpages either if we
+ * can't update reltuples.
*/
- vac_update_relstats(onerel,
- vacrelstats->rel_pages, vacrelstats->rel_tuples,
- vacrelstats->hasindex,
- vacrelstats->scanned_all ? FreezeLimit : InvalidOid);
+ if (vacrelstats->scanned_all)
+ vac_update_relstats(onerel,
+ vacrelstats->rel_pages, vacrelstats->rel_tuples,
+ vacrelstats->hasindex,
+ FreezeLimit);
/* report results to the stats collector, too */
- pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared,
+ pgstat_report_vacuum(RelationGetRelid(onerel),
+ onerel->rd_rel->relisshared,
+ vacrelstats->scanned_all,
vacstmt->analyze, vacrelstats->rel_tuples);
/* and log the action if appropriate */
@@ -221,6 +229,9 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
vacrelstats->tuples_deleted, vacrelstats->rel_tuples,
pg_rusage_show(&ru0))));
}
+
+ if (scanned_all)
+ *scanned_all = vacrelstats->scanned_all;
}
@@ -952,12 +963,14 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
*/
RelationTruncate(onerel, new_rel_pages);
+ /* force relcache inval so all backends reset their rd_targblock */
+ CacheInvalidateRelcache(onerel);
+
/*
* Note: once we have truncated, we *must* keep the exclusive lock until
- * commit. The sinval message that will be sent at commit (as a result of
- * vac_update_relstats()) must be received by other backends, to cause
- * them to reset their rd_targblock values, before they can safely access
- * the table again.
+ * commit. The sinval message won't be sent until commit, and other
+ * backends must see it and reset their rd_targblock values before they
+ * can safely access the table again.
*/
/* update statistics */
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 4a8bf5fd421..e53333d30c9 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.643 2008/12/04 17:51:26 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.644 2008/12/17 09:15:02 heikki Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -5875,7 +5875,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->analyze = false;
n->full = $2;
n->freeze_min_age = $3 ? 0 : -1;
- n->scan_all = $3;
+ n->scan_all = $2 || $3;
n->verbose = $4;
n->relation = NULL;
n->va_cols = NIL;
@@ -5888,7 +5888,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->analyze = false;
n->full = $2;
n->freeze_min_age = $3 ? 0 : -1;
- n->scan_all = $3;
+ n->scan_all = $2 || $3;
n->verbose = $4;
n->relation = $5;
n->va_cols = NIL;
@@ -5900,7 +5900,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->vacuum = true;
n->full = $2;
n->freeze_min_age = $3 ? 0 : -1;
- n->scan_all = $3;
+ n->scan_all = $2 || $3;
n->verbose |= $4;
$$ = (Node *)n;
}
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 0526d169f7e..97539b72c38 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -13,7 +13,7 @@
*
* Copyright (c) 2001-2008, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.185 2008/12/08 15:44:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.186 2008/12/17 09:15:03 heikki Exp $
* ----------
*/
#include "postgres.h"
@@ -1178,7 +1178,7 @@ pgstat_report_autovac(Oid dboid)
* ---------
*/
void
-pgstat_report_vacuum(Oid tableoid, bool shared,
+pgstat_report_vacuum(Oid tableoid, bool shared, bool scanned_all,
bool analyze, PgStat_Counter tuples)
{
PgStat_MsgVacuum msg;
@@ -1189,6 +1189,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_VACUUM);
msg.m_databaseid = shared ? InvalidOid : MyDatabaseId;
msg.m_tableoid = tableoid;
+ msg.m_scanned_all = scanned_all;
msg.m_analyze = analyze;
msg.m_autovacuum = IsAutoVacuumWorkerProcess(); /* is this autovacuum? */
msg.m_vacuumtime = GetCurrentTimestamp();
@@ -3765,12 +3766,14 @@ pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len)
tabentry->autovac_vacuum_timestamp = msg->m_vacuumtime;
else
tabentry->vacuum_timestamp = msg->m_vacuumtime;
- tabentry->n_live_tuples = msg->m_tuples;
+ if (msg->m_scanned_all)
+ tabentry->n_live_tuples = msg->m_tuples;
/* Resetting dead_tuples to 0 is an approximation ... */
tabentry->n_dead_tuples = 0;
if (msg->m_analyze)
{
- tabentry->last_anl_tuples = msg->m_tuples;
+ if (msg->m_scanned_all)
+ tabentry->last_anl_tuples = msg->m_tuples;
if (msg->m_autovacuum)
tabentry->autovac_analyze_timestamp = msg->m_vacuumtime;
else
@@ -3780,7 +3783,7 @@ pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len)
{
/* last_anl_tuples must never exceed n_live_tuples+n_dead_tuples */
tabentry->last_anl_tuples = Min(tabentry->last_anl_tuples,
- msg->m_tuples);
+ tabentry->n_live_tuples);
}
}
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 90446bc4f58..153dbb37f2c 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.81 2008/11/10 00:49:37 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.82 2008/12/17 09:15:03 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -144,10 +144,10 @@ extern void vacuum_delay_point(void);
/* in commands/vacuumlazy.c */
extern void lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
- BufferAccessStrategy bstrategy);
+ BufferAccessStrategy bstrategy, bool *scanned_all);
/* in commands/analyze.c */
extern void analyze_rel(Oid relid, VacuumStmt *vacstmt,
- BufferAccessStrategy bstrategy);
+ BufferAccessStrategy bstrategy, bool update_reltuples);
#endif /* VACUUM_H */
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 119d7b6966d..d2e218ea9c7 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -5,7 +5,7 @@
*
* Copyright (c) 2001-2008, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.79 2008/11/03 01:17:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.80 2008/12/17 09:15:03 heikki Exp $
* ----------
*/
#ifndef PGSTAT_H
@@ -284,6 +284,7 @@ typedef struct PgStat_MsgVacuum
Oid m_tableoid;
bool m_analyze;
bool m_autovacuum;
+ bool m_scanned_all;
TimestampTz m_vacuumtime;
PgStat_Counter m_tuples;
} PgStat_MsgVacuum;
@@ -631,7 +632,7 @@ extern void pgstat_clear_snapshot(void);
extern void pgstat_reset_counters(void);
extern void pgstat_report_autovac(Oid dboid);
-extern void pgstat_report_vacuum(Oid tableoid, bool shared,
+extern void pgstat_report_vacuum(Oid tableoid, bool shared, bool scanned_all,
bool analyze, PgStat_Counter tuples);
extern void pgstat_report_analyze(Relation rel,
PgStat_Counter livetuples,