On 2021-Aug-10, Alvaro Herrera wrote:

> I bring a radical proposal that may be sufficient to close this
> particular hole.  What if we made partition only affected their
> top-level parents to become auto-analyzed, and not any intermediate
> ancestors?  Any intermediate partitioned partitions could be analyzed
> manually if the user wished, and perhaps some reloption could enable
> autovacuum to do it (with the caveat that it'd cause multiple sampling
> of partitions).  I don't yet have a clear picture on how to implement
> this, but I'll explore it while waiting for opinions on the idea.

So, with this patch (a quick and dirty job) we no longer sample all
partitions twice; we no longer propagate the tuple counts to p_0.
We don't have stats on p_0 anymore, only on p and on the individual
partitions.

I didn't move the new #include to a more decent place because
1. that stuff is going to move to partition.c as a new function,
including the new include;
2. that new function also needs to read the reloptions for p_0 to allow
the user to enable stat acquisition for p_0 with "alter table p_0 set
(autovacuum_enabled=1)";
3. need to avoid reporting ancestors of a partition repeatedly, which
forestalls the performance objection about reading reloptions too
frequently.

-- 
Álvaro Herrera         PostgreSQL Developer  —  https://www.EnterpriseDB.com/
>From 064bc88bf94b6b4e1bfc16f0639e1500b17b9bf5 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvhe...@alvh.no-ip.org>
Date: Tue, 10 Aug 2021 13:05:59 -0400
Subject: [PATCH] Propagate counts up only to topmost ancestor

Ignore intermediate partitions, to avoid redundant sampling of
partitions.  If needed, those intermediate partitions can be analyzed
manually.
---
 src/backend/postmaster/pgstat.c | 21 ++++++++++++++++-----
 src/include/pgstat.h            |  9 +++++++--
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 1b54ef74eb..a003966cc8 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -1684,6 +1684,7 @@ pgstat_report_analyze(Relation rel,
  *	counts from the partition to its ancestors.  This is necessary so that
  *	other processes can decide whether to analyze the partitioned tables.
  */
+#include "utils/lsyscache.h"
 void
 pgstat_report_anl_ancestors(Oid relid)
 {
@@ -1700,19 +1701,25 @@ pgstat_report_anl_ancestors(Oid relid)
 	foreach(lc, ancestors)
 	{
 		Oid			ancestor = lfirst_oid(lc);
+		bool		ispartition;
 
-		msg.m_ancestors[msg.m_nancestors] = ancestor;
-		if (++msg.m_nancestors >= PGSTAT_NUM_ANCESTORENTRIES)
+		ispartition = get_rel_relispartition(ancestor);
+
+		msg.m_ancestors[msg.m_nancestors].m_ancestor_id = ancestor;
+		msg.m_ancestors[msg.m_nancestors].m_propagate_up = !ispartition;
+		msg.m_nancestors++;
+
+		if (msg.m_nancestors >= PGSTAT_NUM_ANCESTORENTRIES)
 		{
 			pgstat_send(&msg, offsetof(PgStat_MsgAnlAncestors, m_ancestors[0]) +
-						msg.m_nancestors * sizeof(Oid));
+						msg.m_nancestors * sizeof(PgStat_AnlAncestor));
 			msg.m_nancestors = 0;
 		}
 	}
 
 	if (msg.m_nancestors > 0)
 		pgstat_send(&msg, offsetof(PgStat_MsgAnlAncestors, m_ancestors[0]) +
-					msg.m_nancestors * sizeof(Oid));
+					msg.m_nancestors * sizeof(PgStat_AnlAncestor));
 
 	list_free(ancestors);
 }
@@ -5415,9 +5422,13 @@ pgstat_recv_anl_ancestors(PgStat_MsgAnlAncestors *msg, int len)
 
 	for (int i = 0; i < msg->m_nancestors; i++)
 	{
-		Oid			ancestor_relid = msg->m_ancestors[i];
+		Oid			ancestor_relid;
 		PgStat_StatTabEntry *ancestor;
 
+		if (!msg->m_ancestors[i].m_propagate_up)
+			continue;
+
+		ancestor_relid = msg->m_ancestors[i].m_ancestor_id;
 		ancestor = pgstat_get_tab_entry(dbentry, ancestor_relid, true);
 		ancestor->changes_since_analyze +=
 			tabentry->changes_since_analyze - tabentry->changes_since_analyze_reported;
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 2068a68a5f..46ef88e73b 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -438,9 +438,14 @@ typedef struct PgStat_MsgAnalyze
  *								analyze counters
  * ----------
  */
+typedef struct PgStat_AnlAncestor
+{
+	Oid			m_ancestor_id;
+	bool		m_propagate_up;
+} PgStat_AnlAncestor;
 #define PGSTAT_NUM_ANCESTORENTRIES    \
 	((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(Oid) - sizeof(int))	\
-	 / sizeof(Oid))
+	 / sizeof(PgStat_AnlAncestor))
 
 typedef struct PgStat_MsgAnlAncestors
 {
@@ -448,7 +453,7 @@ typedef struct PgStat_MsgAnlAncestors
 	Oid			m_databaseid;
 	Oid			m_tableoid;
 	int			m_nancestors;
-	Oid			m_ancestors[PGSTAT_NUM_ANCESTORENTRIES];
+	PgStat_AnlAncestor m_ancestors[PGSTAT_NUM_ANCESTORENTRIES];
 } PgStat_MsgAnlAncestors;
 
 /* ----------
-- 
2.20.1

Reply via email to