Commit 48c192c1 authored by Tom Lane's avatar Tom Lane

Revise pgstat's tracking of tuple changes to improve the reliability of

decisions about when to auto-analyze.

The previous code depended on n_live_tuples + n_dead_tuples - last_anl_tuples,
where all three of these numbers could be bad estimates from ANALYZE itself.
Even worse, in the presence of a steady flow of HOT updates and matching
HOT-tuple reclamations, auto-analyze might never trigger at all, even if all
three numbers are exactly right, because n_dead_tuples could hold steady.

To fix, replace last_anl_tuples with an accurately tracked count of the total
number of committed tuple inserts + updates + deletes since the last ANALYZE
on the table.  This can still be compared to the same threshold as before, but
it's much more trustworthy than the old computation.  Tracking this requires
one more intra-transaction counter per modified table within backends, but no
additional memory space in the stats collector.  There probably isn't any
measurable speed difference; if anything it might be a bit faster than before,
since I was able to eliminate some per-tuple arithmetic operations in favor of
adding sums once per (sub)transaction.

Also, simplify the logic around pgstat vacuum and analyze reporting messages
by not trying to fold VACUUM ANALYZE into a single pgstat message.

The original thought behind this patch was to allow scheduling of analyzes
on parent tables by artificially inflating their changes_since_analyze count.
I've left that for a separate patch since this change seems to stand on its
own merit.
parent 6761cff3
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.144 2009/12/29 20:11:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.145 2009/12/30 20:32:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -535,16 +535,13 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
}
/*
* Update pages/tuples stats in pg_class.
* Update pages/tuples stats in pg_class, but not if we're inside a
* VACUUM that got a more precise number.
*/
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
......@@ -565,6 +562,13 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
}
}
/*
* Report ANALYZE to the stats collector, too; likewise, tell it to
* adopt these numbers only if we're not inside a VACUUM that got a
* better number.
*/
pgstat_report_analyze(onerel, update_reltuples, totalrows, totaldeadrows);
/* We skip to here if there were no analyzable columns */
cleanup:
......
......@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.400 2009/12/29 20:11:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.401 2009/12/30 20:32:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1332,7 +1332,6 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
pgstat_report_vacuum(RelationGetRelid(onerel),
onerel->rd_rel->relisshared,
true,
(vacstmt->options & VACOPT_ANALYZE) != 0,
vacrelstats->rel_tuples);
return heldoff;
......
......@@ -29,7 +29,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.125 2009/12/19 01:32:34 sriggs Exp $
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.126 2009/12/30 20:32:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -237,7 +237,6 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
pgstat_report_vacuum(RelationGetRelid(onerel),
onerel->rd_rel->relisshared,
vacrelstats->scanned_all,
(vacstmt->options & VACOPT_ANALYZE) != 0,
vacrelstats->rel_tuples);
/* and log the action if appropriate */
......
......@@ -55,7 +55,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.105 2009/11/16 21:32:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.106 2009/12/30 20:32:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -2591,8 +2591,7 @@ relation_needs_vacanalyze(Oid relid,
{
reltuples = classForm->reltuples;
vactuples = tabentry->n_dead_tuples;
anltuples = tabentry->n_live_tuples + tabentry->n_dead_tuples -
tabentry->last_anl_tuples;
anltuples = tabentry->changes_since_analyze;
vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples;
......
This diff is collapsed.
......@@ -5,7 +5,7 @@
*
* Copyright (c) 2001-2009, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.84 2009/11/28 23:38:08 tgl Exp $
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.85 2009/12/30 20:32:14 tgl Exp $
* ----------
*/
#ifndef PGSTAT_H
......@@ -68,9 +68,9 @@ typedef int64 PgStat_Counter;
* fetched by heap_fetch under the control of simple indexscans for this index.
*
* tuples_inserted/updated/deleted/hot_updated count attempted actions,
* regardless of whether the transaction committed. new_live_tuples and
* new_dead_tuples are properly adjusted depending on commit or abort.
* Note that new_live_tuples and new_dead_tuples can be negative!
* regardless of whether the transaction committed. delta_live_tuples,
* delta_dead_tuples, and changed_tuples are set depending on commit or abort.
* Note that delta_live_tuples and delta_dead_tuples can be negative!
* ----------
*/
typedef struct PgStat_TableCounts
......@@ -85,8 +85,9 @@ typedef struct PgStat_TableCounts
PgStat_Counter t_tuples_deleted;
PgStat_Counter t_tuples_hot_updated;
PgStat_Counter t_new_live_tuples;
PgStat_Counter t_new_dead_tuples;
PgStat_Counter t_delta_live_tuples;
PgStat_Counter t_delta_dead_tuples;
PgStat_Counter t_changed_tuples;
PgStat_Counter t_blocks_fetched;
PgStat_Counter t_blocks_hit;
......@@ -102,14 +103,14 @@ typedef struct PgStat_TableCounts
/* ----------
* PgStat_TableStatus Per-table status within a backend
*
* Most of the event counters are nontransactional, ie, we count events
* Many of the event counters are nontransactional, ie, we count events
* in committed and aborted transactions alike. For these, we just count
* directly in the PgStat_TableStatus. However, new_live_tuples and
* new_dead_tuples must be derived from tuple insertion and deletion counts
* directly in the PgStat_TableStatus. However, delta_live_tuples,
* delta_dead_tuples, and changed_tuples must be derived from event counts
* with awareness of whether the transaction or subtransaction committed or
* aborted. Hence, we also keep a stack of per-(sub)transaction status
* records for every table modified in the current transaction. At commit
* or abort, we propagate tuples_inserted and tuples_deleted up to the
* or abort, we propagate tuples_inserted/updated/deleted up to the
* parent subtransaction level, or out to the parent PgStat_TableStatus,
* as appropriate.
* ----------
......@@ -129,6 +130,7 @@ typedef struct PgStat_TableStatus
typedef struct PgStat_TableXactStatus
{
PgStat_Counter tuples_inserted; /* tuples inserted in (sub)xact */
PgStat_Counter tuples_updated; /* tuples updated in (sub)xact */
PgStat_Counter tuples_deleted; /* tuples deleted in (sub)xact */
int nest_level; /* subtransaction nest level */
/* links to other structs for same relation: */
......@@ -274,7 +276,7 @@ typedef struct PgStat_MsgAutovacStart
/* ----------
* PgStat_MsgVacuum Sent by the backend or autovacuum daemon
* after VACUUM or VACUUM ANALYZE
* after VACUUM
* ----------
*/
typedef struct PgStat_MsgVacuum
......@@ -282,9 +284,8 @@ typedef struct PgStat_MsgVacuum
PgStat_MsgHdr m_hdr;
Oid m_databaseid;
Oid m_tableoid;
bool m_analyze;
bool m_adopt_counts;
bool m_autovacuum;
bool m_scanned_all;
TimestampTz m_vacuumtime;
PgStat_Counter m_tuples;
} PgStat_MsgVacuum;
......@@ -300,6 +301,7 @@ typedef struct PgStat_MsgAnalyze
PgStat_MsgHdr m_hdr;
Oid m_databaseid;
Oid m_tableoid;
bool m_adopt_counts;
bool m_autovacuum;
TimestampTz m_analyzetime;
PgStat_Counter m_live_tuples;
......@@ -478,7 +480,7 @@ typedef struct PgStat_StatTabEntry
PgStat_Counter n_live_tuples;
PgStat_Counter n_dead_tuples;
PgStat_Counter last_anl_tuples;
PgStat_Counter changes_since_analyze;
PgStat_Counter blocks_fetched;
PgStat_Counter blocks_hit;
......@@ -635,11 +637,10 @@ 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, bool scanned_all,
bool analyze, PgStat_Counter tuples);
extern void pgstat_report_analyze(Relation rel,
PgStat_Counter livetuples,
PgStat_Counter deadtuples);
extern void pgstat_report_vacuum(Oid tableoid, bool shared, bool adopt_counts,
PgStat_Counter tuples);
extern void pgstat_report_analyze(Relation rel, bool adopt_counts,
PgStat_Counter livetuples, PgStat_Counter deadtuples);
extern void pgstat_initialize(void);
extern void pgstat_bestart(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment