From 5f3e0e84b274dbbe605cd2d4c2717c14e2cfe787 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 6 Jun 2016 17:44:17 -0400 Subject: [PATCH] Don't reset changes_since_analyze after a selective-columns ANALYZE. If we ANALYZE only selected columns of a table, we should not postpone auto-analyze because of that; other columns may well still need stats updates. As committed, the counter is left alone if a column list is given, whether or not it includes all analyzable columns of the table. Per complaint from Tomasz Ostrowski. It's been like this a long time, so back-patch to all supported branches. Report: --- src/backend/commands/analyze.c | 7 +++++-- src/backend/postmaster/pgstat.c | 15 +++++++++++---- src/include/pgstat.h | 4 +++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 0962933da4..8be58fcbda 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -616,10 +616,13 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, /* * Report ANALYZE to the stats collector, too. However, if doing * inherited stats we shouldn't report, because the stats collector only - * tracks per-table stats. + * tracks per-table stats. Reset the changes_since_analyze counter only + * if we analyzed all columns; otherwise, there is still work for + * auto-analyze to do. */ if (!inh) - pgstat_report_analyze(onerel, totalrows, totaldeadrows); + pgstat_report_analyze(onerel, totalrows, totaldeadrows, + (vacstmt->va_cols == NIL)); /* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */ if (!(vacstmt->options & VACOPT_VACUUM)) diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 4b0966ba83..6838b3e2b1 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -1329,11 +1329,15 @@ pgstat_report_vacuum(Oid tableoid, bool shared, PgStat_Counter tuples) * pgstat_report_analyze() - * * Tell the collector about the table we just analyzed. + * + * Caller must provide new live- and dead-tuples estimates, as well as a + * flag indicating whether to reset the changes_since_analyze counter. * -------- */ void pgstat_report_analyze(Relation rel, - PgStat_Counter livetuples, PgStat_Counter deadtuples) + PgStat_Counter livetuples, PgStat_Counter deadtuples, + bool resetcounter) { PgStat_MsgAnalyze msg; @@ -1370,6 +1374,7 @@ pgstat_report_analyze(Relation rel, msg.m_databaseid = rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId; msg.m_tableoid = RelationGetRelid(rel); msg.m_autovacuum = IsAutoVacuumWorkerProcess(); + msg.m_resetcounter = resetcounter; msg.m_analyzetime = GetCurrentTimestamp(); msg.m_live_tuples = livetuples; msg.m_dead_tuples = deadtuples; @@ -4842,10 +4847,12 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len) tabentry->n_dead_tuples = msg->m_dead_tuples; /* - * We reset changes_since_analyze to zero, forgetting any changes that - * occurred while the ANALYZE was in progress. + * If commanded, reset changes_since_analyze to zero. This forgets any + * changes that were committed while the ANALYZE was in progress, but we + * have no good way to estimate how many of those there were. */ - tabentry->changes_since_analyze = 0; + if (msg->m_resetcounter) + tabentry->changes_since_analyze = 0; if (msg->m_autovacuum) { diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 3dac0220c0..6df6f380c4 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -359,6 +359,7 @@ typedef struct PgStat_MsgAnalyze Oid m_databaseid; Oid m_tableoid; bool m_autovacuum; + bool m_resetcounter; TimestampTz m_analyzetime; PgStat_Counter m_live_tuples; PgStat_Counter m_dead_tuples; @@ -788,7 +789,8 @@ extern void pgstat_report_autovac(Oid dboid); extern void pgstat_report_vacuum(Oid tableoid, bool shared, PgStat_Counter tuples); extern void pgstat_report_analyze(Relation rel, - PgStat_Counter livetuples, PgStat_Counter deadtuples); + PgStat_Counter livetuples, PgStat_Counter deadtuples, + bool resetcounter); extern void pgstat_report_recovery_conflict(int reason); extern void pgstat_report_deadlock(void);