From: Alvaro Herrera <alvherre@alvh.no-ip.org>
To: yuzuko <yuzukohosoya@gmail.com>
Cc: Tomas Vondra <tomas.vondra@enterprisedb.com>
Cc: David Steele <david@pgmasters.net>
Cc: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Cc: Justin Pryzby <pryzby@telsasoft.com>
Cc: Daniel Gustafsson <daniel@yesql.se>
Cc: Amit Langote <amitlangote09@gmail.com>
Cc: Masahiko Sawada <masahiko.sawada@2ndquadrant.com>
Cc: Laurenz Albe <laurenz.albe@cybertec.at>
Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Cc: Greg Stark <stark@mit.edu>
Subject: Re: Autovacuum on partitioned table (autoanalyze)
Date: Sat, 3 Apr 2021 16:42:34 -0300
Message-ID: <20210403194234.GA18917@alvherre.pgsql> (raw)
In-Reply-To: <CAKkQ508EzAG9ib8rRSNozuYhB1e6p_4FzwrG=YRTW2fENT2+BA@mail.gmail.com>
Thanks for the quick rework. I like this design much better and I think
this is pretty close to committable. Here's a rebased copy with some
small cleanups (most notably, avoid calling pgstat_propagate_changes
when the partition doesn't have a tabstat entry; also, free the lists
that are allocated in a couple of places).
I didn't actually verify that it works.
--
Álvaro Herrera Valdivia, Chile
"La primera ley de las demostraciones en vivo es: no trate de usar el sistema.
Escriba un guión que no toque nada para no causar daños." (Jakob Nielsen)
Attachments:
[text/x-diff] v14_autovacuum_on_partitioned_tables.patch (21.8K, ../20210403194234.GA18917@alvherre.pgsql/2-v14_autovacuum_on_partitioned_tables.patch)
download | inline diff:diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.cindex d897bbec2b..5554275e64 100644--- a/src/backend/access/common/reloptions.c+++ b/src/backend/access/common/reloptions.c@@ -108,7 +108,7 @@ static relopt_bool boolRelOpts[] =
{
"autovacuum_enabled",
"Enables autovacuum in this relation",
- RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,+ RELOPT_KIND_HEAP | RELOPT_KIND_TOAST | RELOPT_KIND_PARTITIONED,
ShareUpdateExclusiveLock
},
true
@@ -246,7 +246,7 @@ static relopt_int intRelOpts[] =
{
"autovacuum_analyze_threshold",
"Minimum number of tuple inserts, updates or deletes prior to analyze",
- RELOPT_KIND_HEAP,+ RELOPT_KIND_HEAP | RELOPT_KIND_PARTITIONED,
ShareUpdateExclusiveLock
},
-1, 0, INT_MAX
@@ -420,7 +420,7 @@ static relopt_real realRelOpts[] =
{
"autovacuum_analyze_scale_factor",
"Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
- RELOPT_KIND_HEAP,+ RELOPT_KIND_HEAP | RELOPT_KIND_PARTITIONED,
ShareUpdateExclusiveLock
},
-1, 0.0, 100.0
@@ -1962,12 +1962,11 @@ bytea *
partitioned_table_reloptions(Datum reloptions, bool validate)
{
/*
- * There are no options for partitioned tables yet, but this is able to do- * some validation.+ * autovacuum_enabled, autovacuum_analyze_threshold and+ * autovacuum_analyze_scale_factor are supported for partitioned tables.
*/
- return (bytea *) build_reloptions(reloptions, validate,- RELOPT_KIND_PARTITIONED,- 0, NULL, 0);++ return default_reloptions(reloptions, validate, RELOPT_KIND_PARTITIONED);
}
/*
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sqlindex 5f2541d316..fb41b06539 100644--- a/src/backend/catalog/system_views.sql+++ b/src/backend/catalog/system_views.sql@@ -660,7 +660,7 @@ CREATE VIEW pg_stat_all_tables AS
FROM pg_class C LEFT JOIN
pg_index I ON C.oid = I.indrelid
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
- WHERE C.relkind IN ('r', 't', 'm')+ WHERE C.relkind IN ('r', 't', 'm', 'p')
GROUP BY C.oid, N.nspname, C.relname;
CREATE VIEW pg_stat_xact_all_tables AS
@@ -680,7 +680,7 @@ CREATE VIEW pg_stat_xact_all_tables AS
FROM pg_class C LEFT JOIN
pg_index I ON C.oid = I.indrelid
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
- WHERE C.relkind IN ('r', 't', 'm')+ WHERE C.relkind IN ('r', 't', 'm', 'p')
GROUP BY C.oid, N.nspname, C.relname;
CREATE VIEW pg_stat_sys_tables AS
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.cindex f84616d3d2..35e9a2fc17 100644--- a/src/backend/commands/analyze.c+++ b/src/backend/commands/analyze.c@@ -655,20 +655,22 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
InvalidMultiXactId,
in_outer_xact);
}
+ }- /*- * Now report ANALYZE to the stats collector.- *- * We deliberately don't report to the stats collector when doing- * inherited stats, because the stats collector only 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.- */+ /*+ * Now report ANALYZE to the stats collector.+ *+ * Regarding inherited stats, we report only in the case of declarative+ * partitioning. For partitioning based on inheritance, stats collector+ * only 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 || onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
pgstat_report_analyze(onerel, totalrows, totaldeadrows,
(va_cols == NIL));
- }+
/*
* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup.
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.cindex 23ef23c13e..7ca074a800 100644--- a/src/backend/postmaster/autovacuum.c+++ b/src/backend/postmaster/autovacuum.c@@ -74,7 +74,9 @@
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/namespace.h"
+#include "catalog/partition.h"
#include "catalog/pg_database.h"
+#include "catalog/pg_inherits.h"
#include "commands/dbcommands.h"
#include "commands/vacuum.h"
#include "lib/ilist.h"
@@ -350,6 +352,8 @@ static void autovac_report_activity(autovac_table *tab);
static void autovac_report_workitem(AutoVacuumWorkItem *workitem,
const char *nspname, const char *relname);
static void avl_sigusr2_handler(SIGNAL_ARGS);
+static void pgstat_propagate_changes(Form_pg_class classForm,+ PgStat_StatTabEntry *tabentry);
static void autovac_refresh_stats(void);
@@ -2055,11 +2059,11 @@ do_autovacuum(void)
* Scan pg_class to determine which tables to vacuum.
*
* We do this in two passes: on the first one we collect the list of plain
- * relations and materialized views, and on the second one we collect- * TOAST tables. The reason for doing the second pass is that during it we- * want to use the main relation's pg_class.reloptions entry if the TOAST- * table does not have any, and we cannot obtain it unless we know- * beforehand what's the main table OID.+ * relations, materialized views and partitioned tables, and on the second+ * one we collect TOAST tables. The reason for doing the second pass is+ * that during it we want to use the main relation's pg_class.reloptions+ * entry if the TOAST table does not have any, and we cannot obtain it+ * unless we know beforehand what's the main table OID.
*
* We need to check TOAST tables separately because in cases with short,
* wide tables there might be proportionally much more activity in the
@@ -2082,7 +2086,8 @@ do_autovacuum(void)
bool wraparound;
if (classForm->relkind != RELKIND_RELATION &&
- classForm->relkind != RELKIND_MATVIEW)+ classForm->relkind != RELKIND_MATVIEW &&+ classForm->relkind != RELKIND_PARTITIONED_TABLE)
continue;
relid = classForm->oid;
@@ -2117,6 +2122,16 @@ do_autovacuum(void)
tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
shared, dbentry);
+ /*+ * If this relation is a leaf partition, propagate+ * changes_since_analyze counts to all ancestors.+ */+ if (classForm->relispartition && tabentry &&+ !(classForm->relkind == RELKIND_PARTITIONED_TABLE))+ {+ pgstat_propagate_changes(classForm, tabentry);+ }+
/* Check if it needs vacuum or analyze */
relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
effective_multixact_freeze_max_age,
@@ -2745,6 +2760,7 @@ extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
Assert(((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_RELATION ||
((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_MATVIEW ||
+ ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_PARTITIONED_TABLE ||
((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE);
relopts = extractRelOptions(tup, pg_class_desc, NULL);
@@ -3161,7 +3177,43 @@ relation_needs_vacanalyze(Oid relid,
*/
if (PointerIsValid(tabentry) && AutoVacuumingActive())
{
- reltuples = classForm->reltuples;+ if (classForm->relkind != RELKIND_PARTITIONED_TABLE)+ reltuples = classForm->reltuples;+ else+ {+ /*+ * If the relation is a partitioned table, we must add up+ * children's reltuples.+ */+ List *children;+ ListCell *lc;++ reltuples = 0;++ /* Find all members of inheritance set taking AccessShareLock */+ children = find_all_inheritors(relid, AccessShareLock, NULL);++ foreach(lc, children)+ {+ Oid childOID = lfirst_oid(lc);+ HeapTuple childtuple;+ Form_pg_class childclass;++ childtuple = SearchSysCache1(RELOID, ObjectIdGetDatum(childOID));+ childclass = (Form_pg_class) GETSTRUCT(childtuple);++ /* Skip a partitioned table and foreign partitions */+ if (RELKIND_HAS_STORAGE(childclass->relkind))+ {+ /* Sum up the child's reltuples for its parent table */+ reltuples += childclass->reltuples;+ }+ ReleaseSysCache(childtuple);+ }++ list_free(children);+ }+
vactuples = tabentry->n_dead_tuples;
instuples = tabentry->inserts_since_vacuum;
anltuples = tabentry->changes_since_analyze;
@@ -3312,6 +3364,61 @@ autovac_report_workitem(AutoVacuumWorkItem *workitem,
pgstat_report_activity(STATE_RUNNING, activity);
}
+/*+ * pgstat_propagate_changes+ *+ * Propagate changes_since_analyze counter to all of ancestors+ * to analyze partitioned tables automatically+ *+ * We can decide whether a partitioned table needs auto analyze according to+ * changes_since_analyze which is propagated from all of the leaf partitions.+ * To know the correct difference of partitioned table from the last analyze,+ * we should track changes_since_analyze_reported counter for leaf partitions+ * as well as changes_since_analyze counter. While changes_since_analyze+ * counter tracks the number of changed tuples from the last analyze per+ * partitions, changes_since_analyze_reported counter tracks changes_since_analyze+ * we already propagated to ancestors. Then, we propagate only the difference+ * between these counters to the partitioned table.+ */+static void+pgstat_propagate_changes(Form_pg_class classForm, PgStat_StatTabEntry *tabentry)+{++ float4 anltuples,+ anltuples_reported,+ change_count;+ List *ancestors;+ ListCell *lc;+ Relation parentrel,+ childrel;++ ancestors = get_partition_ancestors(classForm->oid);++ anltuples = tabentry->changes_since_analyze;+ anltuples_reported = tabentry->changes_since_analyze_reported;+ change_count = anltuples - anltuples_reported;++ /* update changes_since_analyze of ancestors */+ if (anltuples > 0 && change_count > 0)+ {+ foreach(lc, ancestors)+ {+ Oid relid = lfirst_oid(lc);++ parentrel = table_open(relid, AccessShareLock);+ pgstat_report_partchanges(parentrel, change_count);+ table_close(parentrel, AccessShareLock);+ }++ /* update own changes_since_analyze_reported */+ childrel = table_open(classForm->oid, AccessShareLock);+ pgstat_report_reportedchanges(childrel, change_count);+ table_close(childrel, AccessShareLock);+ }++ list_free(ancestors);+}+
/*
* AutoVacuumingActive
* Check GUC vars and report whether the autovacuum process should be
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.cindex 4c4b072068..27316f598a 100644--- a/src/backend/postmaster/pgstat.c+++ b/src/backend/postmaster/pgstat.c@@ -343,6 +343,8 @@ static void pgstat_recv_resetreplslotcounter(PgStat_MsgResetreplslotcounter *msg
static void pgstat_recv_autovac(PgStat_MsgAutovacStart *msg, int len);
static void pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len);
static void pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len);
+static void pgstat_recv_partchanges(PgStat_MsgPartChanges *msg, int len);+static void pgstat_recv_reportedchanges(PgStat_MsgReportedChanges *msg, int len);
static void pgstat_recv_archiver(PgStat_MsgArchiver *msg, int len);
static void pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len);
static void pgstat_recv_wal(PgStat_MsgWal *msg, int len);
@@ -1592,6 +1594,9 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
*
* Caller must provide new live- and dead-tuples estimates, as well as a
* flag indicating whether to reset the changes_since_analyze counter.
+ * Exceptional support only changes_since_analyze for partitioned tables,+ * though they don't have any data. This counter will tell us whether+ * partitioned tables need autoanalyze or not.
* --------
*/
void
@@ -1613,23 +1618,31 @@ pgstat_report_analyze(Relation rel,
* be double-counted after commit. (This approach also ensures that the
* collector ends up with the right numbers if we abort instead of
* committing.)
+ *+ * For partitioned tables, we don't report live and dead tuples, because+ * such tables don't have any data.
*/
if (rel->pgstat_info != NULL)
{
PgStat_TableXactStatus *trans;
- for (trans = rel->pgstat_info->trans; trans; trans = trans->upper)+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)+ /* If this rel is partitioned, skip modifying */+ livetuples = deadtuples = 0;+ else
{
- livetuples -= trans->tuples_inserted - trans->tuples_deleted;- deadtuples -= trans->tuples_updated + trans->tuples_deleted;+ for (trans = rel->pgstat_info->trans; trans; trans = trans->upper)+ {+ livetuples -= trans->tuples_inserted - trans->tuples_deleted;+ deadtuples -= trans->tuples_updated + trans->tuples_deleted;+ }+ /* count stuff inserted by already-aborted subxacts, too */+ deadtuples -= rel->pgstat_info->t_counts.t_delta_dead_tuples;+ /* Since ANALYZE's counts are estimates, we could have underflowed */+ livetuples = Max(livetuples, 0);+ deadtuples = Max(deadtuples, 0);
}
- /* count stuff inserted by already-aborted subxacts, too */- deadtuples -= rel->pgstat_info->t_counts.t_delta_dead_tuples;- /* Since ANALYZE's counts are estimates, we could have underflowed */- livetuples = Max(livetuples, 0);- deadtuples = Max(deadtuples, 0);
}
-
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_ANALYZE);
msg.m_databaseid = rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId;
msg.m_tableoid = RelationGetRelid(rel);
@@ -1641,6 +1654,49 @@ pgstat_report_analyze(Relation rel,
pgstat_send(&msg, sizeof(msg));
}
+/* --------+ * pgstat_report_partchanges() -+ *+ * Propagate changes_since_analyze counter from a leaf partition to its parent.+ * --------+ */+void+pgstat_report_partchanges(Relation rel, PgStat_Counter changed_tuples)+{+ PgStat_MsgPartChanges msg;++ if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts)+ return;++ pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_PARTCHANGES);+ msg.m_databaseid = rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId;+ msg.m_tableoid = RelationGetRelid(rel);+ msg.m_changed_tuples = changed_tuples;+ pgstat_send(&msg, sizeof(msg));+}++/* --------+ * pgstat_report_reportedchanges() -+ *+ * Tell the collector changes_since_analyze counter we have already+ * propagated to its ancestors.+ * --------+ */+void+pgstat_report_reportedchanges(Relation rel, PgStat_Counter changed_tuples_reported)+{+ PgStat_MsgReportedChanges msg;++ if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts)+ return;++ pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_REPORTEDCHANGES);+ msg.m_databaseid = rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId;+ msg.m_tableoid = RelationGetRelid(rel);+ msg.m_changed_tuples_reported = changed_tuples_reported;+ pgstat_send(&msg, sizeof(msg));+}+
/* --------
* pgstat_report_recovery_conflict() -
*
@@ -1958,7 +2014,8 @@ pgstat_initstats(Relation rel)
char relkind = rel->rd_rel->relkind;
/* We only count stats for things that have storage */
- if (!RELKIND_HAS_STORAGE(relkind))+ if (!RELKIND_HAS_STORAGE(relkind) &&+ relkind != RELKIND_PARTITIONED_TABLE)
{
rel->pgstat_info = NULL;
return;
@@ -3287,6 +3344,14 @@ PgstatCollectorMain(int argc, char *argv[])
pgstat_recv_analyze(&msg.msg_analyze, len);
break;
+ case PGSTAT_MTYPE_PARTCHANGES:+ pgstat_recv_partchanges(&msg.msg_partchanges, len);+ break;++ case PGSTAT_MTYPE_REPORTEDCHANGES:+ pgstat_recv_reportedchanges(&msg.msg_reportedchanges, len);+ break;+
case PGSTAT_MTYPE_ARCHIVER:
pgstat_recv_archiver(&msg.msg_archiver, len);
break;
@@ -3501,6 +3566,7 @@ pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry, Oid tableoid, bool create)
result->n_live_tuples = 0;
result->n_dead_tuples = 0;
result->changes_since_analyze = 0;
+ result->changes_since_analyze_reported = 0;
result->inserts_since_vacuum = 0;
result->blocks_fetched = 0;
result->blocks_hit = 0;
@@ -4768,6 +4834,7 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
tabentry->n_live_tuples = tabmsg->t_counts.t_delta_live_tuples;
tabentry->n_dead_tuples = tabmsg->t_counts.t_delta_dead_tuples;
tabentry->changes_since_analyze = tabmsg->t_counts.t_changed_tuples;
+ tabentry->changes_since_analyze_reported = 0;
tabentry->inserts_since_vacuum = tabmsg->t_counts.t_tuples_inserted;
tabentry->blocks_fetched = tabmsg->t_counts.t_blocks_fetched;
tabentry->blocks_hit = tabmsg->t_counts.t_blocks_hit;
@@ -4803,6 +4870,7 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
tabentry->n_live_tuples += tabmsg->t_counts.t_delta_live_tuples;
tabentry->n_dead_tuples += tabmsg->t_counts.t_delta_dead_tuples;
tabentry->changes_since_analyze += tabmsg->t_counts.t_changed_tuples;
+ tabentry->changes_since_analyze_reported = 0;
tabentry->inserts_since_vacuum += tabmsg->t_counts.t_tuples_inserted;
tabentry->blocks_fetched += tabmsg->t_counts.t_blocks_fetched;
tabentry->blocks_hit += tabmsg->t_counts.t_blocks_hit;
@@ -5159,7 +5227,10 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
* have no good way to estimate how many of those there were.
*/
if (msg->m_resetcounter)
+ {
tabentry->changes_since_analyze = 0;
+ tabentry->changes_since_analyze_reported = 0;+ }
if (msg->m_autovacuum)
{
@@ -5173,6 +5244,34 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
}
}
+static void+pgstat_recv_partchanges(PgStat_MsgPartChanges *msg, int len)+{+ PgStat_StatDBEntry *dbentry;+ PgStat_StatTabEntry *tabentry;++ dbentry = pgstat_get_db_entry(msg->m_databaseid, true);++ tabentry = pgstat_get_tab_entry(dbentry, msg->m_tableoid, true);++ tabentry->changes_since_analyze += msg->m_changed_tuples;+}+++static void+pgstat_recv_reportedchanges(PgStat_MsgReportedChanges *msg, int len)+{+ PgStat_StatDBEntry *dbentry;+ PgStat_StatTabEntry *tabentry;++ dbentry = pgstat_get_db_entry(msg->m_databaseid, true);++ tabentry = pgstat_get_tab_entry(dbentry, msg->m_tableoid, true);++ tabentry->changes_since_analyze_reported += msg->m_changed_tuples_reported;+}++
/* ----------
* pgstat_recv_archiver() -
diff --git a/src/include/pgstat.h b/src/include/pgstat.hindex 7cd137506e..194003d5d1 100644--- a/src/include/pgstat.h+++ b/src/include/pgstat.h@@ -69,6 +69,8 @@ typedef enum StatMsgType
PGSTAT_MTYPE_AUTOVAC_START,
PGSTAT_MTYPE_VACUUM,
PGSTAT_MTYPE_ANALYZE,
+ PGSTAT_MTYPE_PARTCHANGES,+ PGSTAT_MTYPE_REPORTEDCHANGES,
PGSTAT_MTYPE_ARCHIVER,
PGSTAT_MTYPE_BGWRITER,
PGSTAT_MTYPE_WAL,
@@ -126,6 +128,7 @@ typedef struct PgStat_TableCounts
PgStat_Counter t_delta_live_tuples;
PgStat_Counter t_delta_dead_tuples;
PgStat_Counter t_changed_tuples;
+ PgStat_Counter t_changed_tuples_reported;
PgStat_Counter t_blocks_fetched;
PgStat_Counter t_blocks_hit;
@@ -429,6 +432,32 @@ typedef struct PgStat_MsgAnalyze
PgStat_Counter m_dead_tuples;
} PgStat_MsgAnalyze;
+/* ----------+ * PgStat_MsgPartChanges Sent by the autovacuum deamon to propagate+ * the changed_tuples counter.+ * ----------+ */+typedef struct PgStat_MsgPartChanges+{+ PgStat_MsgHdr m_hdr;+ Oid m_databaseid;+ Oid m_tableoid;+ PgStat_Counter m_changed_tuples;+} PgStat_MsgPartChanges;++/* ----------+ * PgStat_MsgReportedChanges Sent by the autovacuum deamon to update+ * changed_tuples_reported.+ * ----------+ */+typedef struct PgStat_MsgReportedChanges+{+ PgStat_MsgHdr m_hdr;+ Oid m_databaseid;+ Oid m_tableoid;+ PgStat_Counter m_changed_tuples_reported;+} PgStat_MsgReportedChanges;+
/* ----------
* PgStat_MsgArchiver Sent by the archiver to update statistics.
@@ -674,6 +703,8 @@ typedef union PgStat_Msg
PgStat_MsgAutovacStart msg_autovacuum_start;
PgStat_MsgVacuum msg_vacuum;
PgStat_MsgAnalyze msg_analyze;
+ PgStat_MsgPartChanges msg_partchanges;+ PgStat_MsgReportedChanges msg_reportedchanges;
PgStat_MsgArchiver msg_archiver;
PgStat_MsgBgWriter msg_bgwriter;
PgStat_MsgWal msg_wal;
@@ -769,6 +800,7 @@ typedef struct PgStat_StatTabEntry
PgStat_Counter n_live_tuples;
PgStat_Counter n_dead_tuples;
PgStat_Counter changes_since_analyze;
+ PgStat_Counter changes_since_analyze_reported;
PgStat_Counter inserts_since_vacuum;
PgStat_Counter blocks_fetched;
@@ -975,7 +1007,8 @@ extern void pgstat_report_vacuum(Oid tableoid, bool shared,
extern void pgstat_report_analyze(Relation rel,
PgStat_Counter livetuples, PgStat_Counter deadtuples,
bool resetcounter);
-+extern void pgstat_report_partchanges(Relation rel, PgStat_Counter changes_tuples);+extern void pgstat_report_reportedchanges(Relation rel, PgStat_Counter changes_tuples_reported);
extern void pgstat_report_recovery_conflict(int reason);
extern void pgstat_report_deadlock(void);
extern void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount);
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.outindex 9b59a7b4a5..954afb9a45 100644--- a/src/test/regress/expected/rules.out+++ b/src/test/regress/expected/rules.out@@ -1806,7 +1806,7 @@ pg_stat_all_tables| SELECT c.oid AS relid,
FROM ((pg_class c
LEFT JOIN pg_index i ON ((c.oid = i.indrelid)))
LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
- WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]))+ WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char", 'p'::"char"]))
GROUP BY c.oid, n.nspname, c.relname;
pg_stat_archiver| SELECT s.archived_count,
s.last_archived_wal,
@@ -2209,7 +2209,7 @@ pg_stat_xact_all_tables| SELECT c.oid AS relid,
FROM ((pg_class c
LEFT JOIN pg_index i ON ((c.oid = i.indrelid)))
LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
- WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]))+ WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char", 'p'::"char"]))
GROUP BY c.oid, n.nspname, c.relname;
pg_stat_xact_sys_tables| SELECT pg_stat_xact_all_tables.relid,
pg_stat_xact_all_tables.schemaname,
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: alvherre@alvh.no-ip.org, yuzukohosoya@gmail.com, tomas.vondra@enterprisedb.com, david@pgmasters.net, horikyota.ntt@gmail.com, pryzby@telsasoft.com, daniel@yesql.se, amitlangote09@gmail.com, masahiko.sawada@2ndquadrant.com, laurenz.albe@cybertec.at, pgsql-hackers@lists.postgresql.org, stark@mit.edu
Subject: Re: Autovacuum on partitioned table (autoanalyze)
In-Reply-To: <20210403194234.GA18917@alvherre.pgsql>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox