mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
Integrate autovacuum functionality into the backend. There's still a
few loose ends to be dealt with, but it seems to work. Alvaro Herrera, based on the contrib code by Matthew O'Connor.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.86 2005/05/06 17:24:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.87 2005/07/14 05:13:39 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "parser/parse_expr.h"
|
||||
#include "parser/parse_oper.h"
|
||||
#include "parser/parse_relation.h"
|
||||
#include "pgstat.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/datum.h"
|
||||
@@ -77,7 +78,7 @@ static void compute_index_stats(Relation onerel, double totalrows,
|
||||
MemoryContext col_context);
|
||||
static VacAttrStats *examine_attribute(Relation onerel, int attnum);
|
||||
static int acquire_sample_rows(Relation onerel, HeapTuple *rows,
|
||||
int targrows, double *totalrows);
|
||||
int targrows, double *totalrows, double *totaldeadrows);
|
||||
static double random_fract(void);
|
||||
static double init_selection_state(int n);
|
||||
static double get_next_S(double t, int n, double *stateptr);
|
||||
@@ -108,7 +109,8 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
|
||||
AnlIndexData *indexdata;
|
||||
int targrows,
|
||||
numrows;
|
||||
double totalrows;
|
||||
double totalrows,
|
||||
totaldeadrows;
|
||||
HeapTuple *rows;
|
||||
|
||||
if (vacstmt->verbose)
|
||||
@@ -309,6 +311,14 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
|
||||
*/
|
||||
if (attr_cnt <= 0 && !analyzableindex)
|
||||
{
|
||||
/*
|
||||
* We report that the table is empty; this is just so that the
|
||||
* autovacuum code doesn't go nuts trying to get stats about
|
||||
* a zero-column table.
|
||||
*/
|
||||
if (!vacstmt->vacuum)
|
||||
pgstat_report_analyze(RelationGetRelid(onerel), 0, 0);
|
||||
|
||||
vac_close_indexes(nindexes, Irel, AccessShareLock);
|
||||
relation_close(onerel, AccessShareLock);
|
||||
return;
|
||||
@@ -340,7 +350,8 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
|
||||
* Acquire the sample rows
|
||||
*/
|
||||
rows = (HeapTuple *) palloc(targrows * sizeof(HeapTuple));
|
||||
numrows = acquire_sample_rows(onerel, rows, targrows, &totalrows);
|
||||
numrows = acquire_sample_rows(onerel, rows, targrows,
|
||||
&totalrows, &totaldeadrows);
|
||||
|
||||
/*
|
||||
* Compute the statistics. Temporary results during the calculations
|
||||
@@ -423,6 +434,10 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
|
||||
totalindexrows,
|
||||
false);
|
||||
}
|
||||
|
||||
/* report results to the stats collector, too */
|
||||
pgstat_report_analyze(RelationGetRelid(onerel), totalrows,
|
||||
totaldeadrows);
|
||||
}
|
||||
|
||||
/* Done with indexes */
|
||||
@@ -752,23 +767,25 @@ BlockSampler_Next(BlockSampler bs)
|
||||
* the number of different blocks represented by the sample tends to be
|
||||
* too small. We can live with that for now. Improvements are welcome.
|
||||
*
|
||||
* We also estimate the total number of rows in the table, and return that
|
||||
* into *totalrows. An important property of this sampling method is that
|
||||
* because we do look at a statistically unbiased set of blocks, we should
|
||||
* get an unbiased estimate of the average number of live rows per block.
|
||||
* The previous sampling method put too much credence in the row density near
|
||||
* the start of the table.
|
||||
* We also estimate the total numbers of live and dead rows in the table,
|
||||
* and return them into *totalrows and *totaldeadrows, respectively.
|
||||
*
|
||||
* An important property of this sampling method is that because we do
|
||||
* look at a statistically unbiased set of blocks, we should get
|
||||
* unbiased estimates of the average numbers of live and dead rows per
|
||||
* block. The previous sampling method put too much credence in the row
|
||||
* density near the start of the table.
|
||||
*
|
||||
* The returned list of tuples is in order by physical position in the table.
|
||||
* (We will rely on this later to derive correlation estimates.)
|
||||
*/
|
||||
static int
|
||||
acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
|
||||
double *totalrows)
|
||||
double *totalrows, double *totaldeadrows)
|
||||
{
|
||||
int numrows = 0; /* # rows collected */
|
||||
double liverows = 0; /* # rows seen */
|
||||
double deadrows = 0;
|
||||
double deadrows = 0; /* # dead rows seen */
|
||||
double rowstoskip = -1; /* -1 means not set yet */
|
||||
BlockNumber totalblocks;
|
||||
BlockSamplerData bs;
|
||||
@@ -864,11 +881,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Count dead rows, but not empty slots. This information
|
||||
* is currently not used, but it seems likely we'll want
|
||||
* it someday.
|
||||
*/
|
||||
/* Count dead rows, but not empty slots */
|
||||
if (targtuple.t_data != NULL)
|
||||
deadrows += 1;
|
||||
}
|
||||
@@ -890,12 +903,18 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
|
||||
qsort((void *) rows, numrows, sizeof(HeapTuple), compare_rows);
|
||||
|
||||
/*
|
||||
* Estimate total number of live rows in relation.
|
||||
* Estimate total numbers of rows in relation.
|
||||
*/
|
||||
if (bs.m > 0)
|
||||
{
|
||||
*totalrows = floor((liverows * totalblocks) / bs.m + 0.5);
|
||||
*totaldeadrows = floor((deadrows * totalblocks) / bs.m + 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
*totalrows = 0.0;
|
||||
*totaldeadrows = 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emit some interesting relation info
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.310 2005/06/14 22:15:32 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.311 2005/07/14 05:13:39 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -166,7 +166,8 @@ static TransactionId FreezeLimit;
|
||||
|
||||
|
||||
/* non-export function prototypes */
|
||||
static List *get_rel_oids(const RangeVar *vacrel, const char *stmttype);
|
||||
static List *get_rel_oids(List *relids, const RangeVar *vacrel,
|
||||
const char *stmttype);
|
||||
static void vac_update_dbstats(Oid dbid,
|
||||
TransactionId vacuumXID,
|
||||
TransactionId frozenXID);
|
||||
@@ -221,9 +222,18 @@ static bool enough_space(VacPage vacpage, Size len);
|
||||
|
||||
/*
|
||||
* Primary entry point for VACUUM and ANALYZE commands.
|
||||
*
|
||||
* relids is normally NIL; if it is not, then it provides the list of
|
||||
* relation OIDs to be processed, and vacstmt->relation is ignored.
|
||||
* (The non-NIL case is currently only used by autovacuum.)
|
||||
*
|
||||
* It is the caller's responsibility that both vacstmt and relids
|
||||
* (if given) be allocated in a memory context that won't disappear
|
||||
* at transaction commit. In fact this context must be QueryContext
|
||||
* to avoid complaints from PreventTransactionChain.
|
||||
*/
|
||||
void
|
||||
vacuum(VacuumStmt *vacstmt)
|
||||
vacuum(VacuumStmt *vacstmt, List *relids)
|
||||
{
|
||||
const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
|
||||
TransactionId initialOldestXmin = InvalidTransactionId;
|
||||
@@ -302,11 +312,14 @@ vacuum(VacuumStmt *vacstmt)
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
|
||||
/* Assume we are processing everything unless one table is mentioned */
|
||||
all_rels = (vacstmt->relation == NULL);
|
||||
/* Remember whether we are processing everything in the DB */
|
||||
all_rels = (relids == NIL && vacstmt->relation == NULL);
|
||||
|
||||
/* Build list of relations to process (note this lives in vac_context) */
|
||||
relations = get_rel_oids(vacstmt->relation, stmttype);
|
||||
/*
|
||||
* Build list of relations to process, unless caller gave us one.
|
||||
* (If we build one, we put it in vac_context for safekeeping.)
|
||||
*/
|
||||
relations = get_rel_oids(relids, vacstmt->relation, stmttype);
|
||||
|
||||
if (vacstmt->vacuum && all_rels)
|
||||
{
|
||||
@@ -512,11 +525,15 @@ vacuum(VacuumStmt *vacstmt)
|
||||
* per-relation transactions.
|
||||
*/
|
||||
static List *
|
||||
get_rel_oids(const RangeVar *vacrel, const char *stmttype)
|
||||
get_rel_oids(List *relids, const RangeVar *vacrel, const char *stmttype)
|
||||
{
|
||||
List *oid_list = NIL;
|
||||
MemoryContext oldcontext;
|
||||
|
||||
/* List supplied by VACUUM's caller? */
|
||||
if (relids)
|
||||
return relids;
|
||||
|
||||
if (vacrel)
|
||||
{
|
||||
/* Process a specific relation */
|
||||
@@ -1146,6 +1163,10 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
|
||||
/* update statistics in pg_class */
|
||||
vac_update_relstats(RelationGetRelid(onerel), vacrelstats->rel_pages,
|
||||
vacrelstats->rel_tuples, vacrelstats->hasindex);
|
||||
|
||||
/* report results to the stats collector, too */
|
||||
pgstat_report_vacuum(RelationGetRelid(onerel), vacstmt->analyze,
|
||||
vacrelstats->rel_tuples);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.54 2005/05/19 21:35:46 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.55 2005/07/14 05:13:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "access/xlog.h"
|
||||
#include "commands/vacuum.h"
|
||||
#include "miscadmin.h"
|
||||
#include "pgstat.h"
|
||||
#include "storage/freespace.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/lsyscache.h"
|
||||
@@ -179,6 +180,10 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
|
||||
vacrelstats->rel_pages,
|
||||
vacrelstats->rel_tuples,
|
||||
hasindex);
|
||||
|
||||
/* report results to the stats collector, too */
|
||||
pgstat_report_vacuum(RelationGetRelid(onerel), vacstmt->analyze,
|
||||
vacrelstats->rel_tuples);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user