aboutsummaryrefslogtreecommitdiff
path: root/src/backend/postmaster/pgstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/postmaster/pgstat.c')
-rw-r--r--src/backend/postmaster/pgstat.c108
1 files changed, 99 insertions, 9 deletions
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 5ba776e7894..958183dd69d 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -38,6 +38,7 @@
#include "access/transam.h"
#include "access/twophase_rmgr.h"
#include "access/xact.h"
+#include "catalog/partition.h"
#include "catalog/pg_database.h"
#include "catalog/pg_proc.h"
#include "common/ip.h"
@@ -343,6 +344,7 @@ 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_anl_ancestors(PgStat_MsgAnlAncestors *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,21 +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);
@@ -1639,6 +1654,48 @@ pgstat_report_analyze(Relation rel,
msg.m_live_tuples = livetuples;
msg.m_dead_tuples = deadtuples;
pgstat_send(&msg, sizeof(msg));
+
+}
+
+/*
+ * pgstat_report_anl_ancestors
+ *
+ * Send list of partitioned table ancestors of the given partition to the
+ * collector. The collector is in charge of propagating the analyze tuple
+ * counts from the partition to its ancestors. This is necessary so that
+ * other processes can decide whether to analyze the partitioned tables.
+ */
+void
+pgstat_report_anl_ancestors(Oid relid)
+{
+ PgStat_MsgAnlAncestors msg;
+ List *ancestors;
+ ListCell *lc;
+
+ pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_ANL_ANCESTORS);
+ msg.m_databaseid = MyDatabaseId;
+ msg.m_tableoid = relid;
+ msg.m_nancestors = 0;
+
+ ancestors = get_partition_ancestors(relid);
+ foreach(lc, ancestors)
+ {
+ Oid ancestor = lfirst_oid(lc);
+
+ msg.m_ancestors[msg.m_nancestors] = ancestor;
+ if (++msg.m_nancestors >= PGSTAT_NUM_ANCESTORENTRIES)
+ {
+ pgstat_send(&msg, offsetof(PgStat_MsgAnlAncestors, m_ancestors[0]) +
+ msg.m_nancestors * sizeof(Oid));
+ msg.m_nancestors = 0;
+ }
+ }
+
+ if (msg.m_nancestors > 0)
+ pgstat_send(&msg, offsetof(PgStat_MsgAnlAncestors, m_ancestors[0]) +
+ msg.m_nancestors * sizeof(Oid));
+
+ list_free(ancestors);
}
/* --------
@@ -1958,7 +2015,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 +3345,10 @@ PgstatCollectorMain(int argc, char *argv[])
pgstat_recv_analyze(&msg.msg_analyze, len);
break;
+ case PGSTAT_MTYPE_ANL_ANCESTORS:
+ pgstat_recv_anl_ancestors(&msg.msg_anl_ancestors, len);
+ break;
+
case PGSTAT_MTYPE_ARCHIVER:
pgstat_recv_archiver(&msg.msg_archiver, len);
break;
@@ -3501,6 +3563,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 +4831,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 +5223,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 +5240,29 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
}
}
+static void
+pgstat_recv_anl_ancestors(PgStat_MsgAnlAncestors *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);
+
+ for (int i = 0; i < msg->m_nancestors; i++)
+ {
+ Oid ancestor_relid = msg->m_ancestors[i];
+ PgStat_StatTabEntry *ancestor;
+
+ ancestor = pgstat_get_tab_entry(dbentry, ancestor_relid, true);
+ ancestor->changes_since_analyze +=
+ tabentry->changes_since_analyze - tabentry->changes_since_analyze_reported;
+ }
+
+ tabentry->changes_since_analyze_reported = tabentry->changes_since_analyze;
+
+}
/* ----------
* pgstat_recv_archiver() -