public inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v8 2/2] report (partial) progress of other index AMs
6+ messages / 4 participants
[nested] [flat]

* [PATCH v8 2/2] report (partial) progress of other index AMs
@ 2019-02-26 17:34 Alvaro Herrera <[email protected]>
  0 siblings, 0 replies; 6+ messages in thread

From: Alvaro Herrera @ 2019-02-26 17:34 UTC (permalink / raw)

---
 contrib/bloom/blinsert.c              | 2 +-
 src/backend/access/brin/brin.c        | 2 +-
 src/backend/access/gin/gininsert.c    | 2 +-
 src/backend/access/gist/gistbuild.c   | 2 +-
 src/backend/access/hash/hash.c        | 6 +++++-
 src/backend/access/hash/hashsort.c    | 6 ++++++
 src/backend/access/spgist/spginsert.c | 2 +-
 7 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/contrib/bloom/blinsert.c b/contrib/bloom/blinsert.c
index 48f35d39990..4b2186b8dda 100644
--- a/contrib/bloom/blinsert.c
+++ b/contrib/bloom/blinsert.c
@@ -142,7 +142,7 @@ blbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	initCachedPage(&buildstate);
 
 	/* Do the heap scan */
-	reltuples = table_index_build_scan(heap, index, indexInfo, true, false,
+	reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
 									   bloomBuildCallback, (void *) &buildstate,
 									   NULL);
 
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 54273f754f6..5c2b0c76358 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -720,7 +720,7 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	 * Now scan the relation.  No syncscan allowed here because we want the
 	 * heap blocks in physical order.
 	 */
-	reltuples = table_index_build_scan(heap, index, indexInfo, false, false,
+	reltuples = table_index_build_scan(heap, index, indexInfo, false, true,
 									   brinbuildCallback, (void *) state, NULL);
 
 	/* process the final batch */
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index b4b0213f76f..edc353a7fe0 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -395,7 +395,7 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	 * Do the heap scan.  We disallow sync scan here because dataPlaceToPage
 	 * prefers to receive tuples in TID order.
 	 */
-	reltuples = table_index_build_scan(heap, index, indexInfo, false, false,
+	reltuples = table_index_build_scan(heap, index, indexInfo, false, true,
 									   ginBuildCallback, (void *) &buildstate,
 									   NULL);
 
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index 771bd2962a7..6024671989e 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -205,7 +205,7 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	/*
 	 * Do the heap scan.
 	 */
-	reltuples = table_index_build_scan(heap, index, indexInfo, true, false,
+	reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
 									   gistBuildCallback,
 									   (void *) &buildstate, NULL);
 
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 6b38dd9c0e9..048e40e46fa 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -23,9 +23,11 @@
 #include "access/relscan.h"
 #include "access/tableam.h"
 #include "catalog/index.h"
+#include "commands/progress.h"
 #include "commands/vacuum.h"
 #include "miscadmin.h"
 #include "optimizer/plancat.h"
+#include "pgstat.h"
 #include "utils/builtins.h"
 #include "utils/index_selfuncs.h"
 #include "utils/rel.h"
@@ -161,9 +163,11 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 	buildstate.heapRel = heap;
 
 	/* do the heap scan */
-	reltuples = table_index_build_scan(heap, index, indexInfo, true, false,
+	reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
 									   hashbuildCallback,
 									   (void *) &buildstate, NULL);
+	pgstat_progress_update_param(PROGRESS_CREATEIDX_TUPLES_TOTAL,
+								 buildstate.indtuples);
 
 	if (buildstate.spool)
 	{
diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c
index 8c55436b193..00a57470a77 100644
--- a/src/backend/access/hash/hashsort.c
+++ b/src/backend/access/hash/hashsort.c
@@ -26,7 +26,9 @@
 #include "postgres.h"
 
 #include "access/hash.h"
+#include "commands/progress.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "utils/tuplesort.h"
 
 
@@ -116,6 +118,7 @@ void
 _h_indexbuild(HSpool *hspool, Relation heapRel)
 {
 	IndexTuple	itup;
+	long		tups_done = 0;
 #ifdef USE_ASSERT_CHECKING
 	uint32		hashkey = 0;
 #endif
@@ -141,5 +144,8 @@ _h_indexbuild(HSpool *hspool, Relation heapRel)
 #endif
 
 		_hash_doinsert(hspool->index, itup, heapRel);
+
+		pgstat_progress_update_param(PROGRESS_CREATEIDX_TUPLES_DONE,
+									 ++tups_done);
 	}
 }
diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c
index 282d6998cf0..b06feafdc24 100644
--- a/src/backend/access/spgist/spginsert.c
+++ b/src/backend/access/spgist/spginsert.c
@@ -143,7 +143,7 @@ spgbuild(Relation heap, Relation index, IndexInfo *indexInfo)
 											  "SP-GiST build temporary context",
 											  ALLOCSET_DEFAULT_SIZES);
 
-	reltuples = table_index_build_scan(heap, index, indexInfo, true, false,
+	reltuples = table_index_build_scan(heap, index, indexInfo, true, true,
 									   spgistBuildCallback, (void *) &buildstate,
 									   NULL);
 
-- 
2.17.1


--7AUc2qLy4jB3hD7Z--





^ permalink  raw  reply  [nested|flat] 6+ messages in thread

* Re: [PATCH] Add sampling statistics to autoanalyze log output
@ 2026-01-19 16:33 Tatsuya Kawata <[email protected]>
  2026-02-10 15:18 ` Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
  0 siblings, 1 reply; 6+ messages in thread

From: Tatsuya Kawata @ 2026-01-19 16:33 UTC (permalink / raw)
  To: Fujii Masao <[email protected]>; +Cc: [email protected] <[email protected]>; Chao Li <[email protected]>; pgsql-hackers

Hi Fujii-san, Chao-san,

Sorry for the late reply.
I have addressed your comments in the attached v4 patch.

> child_sampling_stats is only used inside if (childblocks > 0), so it
would be better to just define it there.

Fixed.


> SamplingStats is a very generic name, maybe rename to
AnalyzeSamplingStats or something else.

Fixed. I changed the struct name.


> > With this change, we would end up reporting nearly the same sampling
> > information twice, for example:
> >
> >     INFO:  analyzing "public.ft"
> >     INFO:  "ft": table contains 10 rows, 10 rows in sample
> >     INFO:  finished analyzing table "postgres.public.ft"
> >     sampling: 10 rows in sample, 10 estimated total rows
> >
> > Wouldn't it be less confusing to avoid reporting the second sampling
line?
>
> I agree, that would be better. I'll fix this.

Fixed. I removed the duplicated messages.


> > I'm not sure it's acceptable to change the FDW API and require
> > FDW authors to update their extensions, especially since
> > the benefit on the FDW side seems limited at this point.
>
> I agree that it's premature to require FDW-side changes at this stage.
I'll remove those modifications.

Fixed. I reverted the FDW API changes, so no modifications are required for
the FDW API.


> > You may need to update src/tools/pgindent/typedefs.list.
>
> Thank you! I'll check and update it.

Done. Thank you for pointing this out!


> > Based on my testing, the aggregated values look incorrect.
> > In the example below, both t_0 and t_1 report 5,000,000 live rows,
> > but the aggregated result is 6,779,052. Is that the expected
> > aggregation behavior?
>
> I had misunderstood the sampling behavior for inheritance tables. I
initially thought it would be straightforward to display the sum of child
table values for the parent table. However, the parent table's sampling
logic proportionally distributes samples from inherited child tables based
on their relative block counts, and stores that as the parent's statistics.
Therefore, simply changing the log output to show summed values would imply
a change in the sampling methodology itself. While such a modification
might be possible in the future, it would deviate from the original purpose
of this patch, which is to align the log output between ANALYZE VERBOSE and
autoanalyze. For now, I'll exclude this from the current patch.


I have excluded this modification from v4 patch. With v4, the log output
now shows per-child sampling statistics for inheritance trees and
partitioned tables, which matches the current behavior.
I also conducted several patterns of tests to ensure new log output matches
current output. I have attached a SETUP SQL script(setup_tables.sql) and
test results(CURRENT:verboselog_current.log, APPLIED
PATCH:verboselog_after_patch.log) demonstrating that the ANALYZE VERBOSE
output which is the same as the autoanalyze log format.

Regards,
Tatsuya Kawata


Attachments:

  [application/octet-stream] verboselog_after_patch.log (10.4K, ../../CAHza6qfeiPDNZmb-T+gUYm6ZWQhZWFSf64YxMjQr7ZfPuF38cQ@mail.gmail.com/3-verboselog_after_patch.log)
  download

  [application/octet-stream] verboselog_current.log (10.5K, ../../CAHza6qfeiPDNZmb-T+gUYm6ZWQhZWFSf64YxMjQr7ZfPuF38cQ@mail.gmail.com/4-verboselog_current.log)
  download

  [application/octet-stream] setup_tables.sql (4.7K, ../../CAHza6qfeiPDNZmb-T+gUYm6ZWQhZWFSf64YxMjQr7ZfPuF38cQ@mail.gmail.com/5-setup_tables.sql)
  download

  [application/octet-stream] v4-0001-Add-sampling-statistics-to-autoanalyze-log-output.patch (12.3K, ../../CAHza6qfeiPDNZmb-T+gUYm6ZWQhZWFSf64YxMjQr7ZfPuF38cQ@mail.gmail.com/6-v4-0001-Add-sampling-statistics-to-autoanalyze-log-output.patch)
  download | inline diff:
From c6537417b20a7db114081ea5e76ba87b6f443903 Mon Sep 17 00:00:00 2001
From: TatsuyaKawata <[email protected]>
Date: Mon, 19 Jan 2026 23:20:23 +0900
Subject: [PATCH v4] Add sampling statistics to autoanalyze log output

Previously, autoanalyze log messages only showed buffer usage, WAL usage,
and system usage statistics. However, ANALYZE VERBOSE showed additional
sampling statistics including pages scanned, live rows, and dead rows
found during sampling. This made it difficult to understand the sampling
behavior from autoanalyze logs alone.

This patch unifies the logging by adding sampling statistics to the
autoanalyze log output. The new log format includes:
- Number of pages scanned out of total pages
- Live rows and dead rows found during sampling
- Number of rows in sample and estimated total rows

To support this change, a new AnalyzeSamplingStats struct is introduced in
vacuum.h to collect and pass sampling statistics.

Author: Tatsuya Kawata <[email protected]>
Reviewed-by: Fujii Masao <[email protected]>
Reviewed-by: Sami Imseih <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/CAHza6qcN%3DPaGqo8CGgrqd%2BnaOwY_pLGiwEq6u%3D%2BASZZNL9zi9A%40mail.gmail.com#26a70a815cc922b7513e71fc0c445ff3
---
 contrib/file_fdw/file_fdw.c         |   9 --
 contrib/postgres_fdw/postgres_fdw.c |   8 --
 src/backend/commands/analyze.c      | 124 ++++++++++++++++++++++------
 src/include/commands/vacuum.h       |  16 ++++
 src/tools/pgindent/typedefs.list    |   1 +
 5 files changed, 116 insertions(+), 42 deletions(-)

diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
index 33a37d832ce..5db29cc33e2 100644
--- a/contrib/file_fdw/file_fdw.c
+++ b/contrib/file_fdw/file_fdw.c
@@ -1327,14 +1327,5 @@ file_acquire_sample_rows(Relation onerel, int elevel,
 	pfree(values);
 	pfree(nulls);
 
-	/*
-	 * Emit some interesting relation info
-	 */
-	ereport(elevel,
-			(errmsg("\"%s\": file contains %.0f rows; "
-					"%d rows in sample",
-					RelationGetRelationName(onerel),
-					*totalrows, numrows)));
-
 	return numrows;
 }
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 3572689e33b..736502b9224 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -5286,14 +5286,6 @@ postgresAcquireSampleRowsFunc(Relation relation, int elevel,
 	else
 		*totalrows = reltuples;
 
-	/*
-	 * Emit some interesting relation info
-	 */
-	ereport(elevel,
-			(errmsg("\"%s\": table contains %.0f rows, %d rows in sample",
-					RelationGetRelationName(relation),
-					*totalrows, astate.numrows)));
-
 	return astate.numrows;
 }
 
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index a483424152c..a1f95ba6cad 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -86,11 +86,13 @@ static VacAttrStats *examine_attribute(Relation onerel, int attnum,
 									   Node *index_expr);
 static int	acquire_sample_rows(Relation onerel, int elevel,
 								HeapTuple *rows, int targrows,
-								double *totalrows, double *totaldeadrows);
+								double *totalrows, double *totaldeadrows,
+								AnalyzeSamplingStats *sampling_stats);
 static int	compare_rows(const void *a, const void *b, void *arg);
 static int	acquire_inherited_sample_rows(Relation onerel, int elevel,
 										  HeapTuple *rows, int targrows,
-										  double *totalrows, double *totaldeadrows);
+										  double *totalrows, double *totaldeadrows,
+										  List **sampling_stats_list);
 static void update_attstats(Oid relid, bool inh,
 							int natts, VacAttrStats **vacattrstats);
 static Datum std_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
@@ -187,9 +189,7 @@ analyze_rel(Oid relid, RangeVar *relation,
 	if (onerel->rd_rel->relkind == RELKIND_RELATION ||
 		onerel->rd_rel->relkind == RELKIND_MATVIEW)
 	{
-		/* Regular table, so we'll use the regular row acquisition function */
-		acquirefunc = acquire_sample_rows;
-		/* Also get regular table's size */
+		/* Get regular table's size */
 		relpages = RelationGetNumberOfBlocks(onerel);
 	}
 	else if (onerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
@@ -302,6 +302,8 @@ do_analyze_rel(Relation onerel, const VacuumParams params,
 	double		totalrows,
 				totaldeadrows;
 	HeapTuple  *rows;
+	AnalyzeSamplingStats sampling_stats = {0};
+	List	   *sampling_stats_list = NIL;
 	PGRUsage	ru0;
 	TimestampTz starttime = 0;
 	MemoryContext caller_context;
@@ -535,11 +537,17 @@ do_analyze_rel(Relation onerel, const VacuumParams params,
 	if (inh)
 		numrows = acquire_inherited_sample_rows(onerel, elevel,
 												rows, targrows,
-												&totalrows, &totaldeadrows);
-	else
+												&totalrows, &totaldeadrows,
+												&sampling_stats_list);
+	else if (onerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
 		numrows = (*acquirefunc) (onerel, elevel,
 								  rows, targrows,
 								  &totalrows, &totaldeadrows);
+	else
+		numrows = acquire_sample_rows(onerel, elevel,
+									  rows, targrows,
+									  &totalrows, &totaldeadrows,
+									  &sampling_stats);
 
 	/*
 	 * Compute the statistics.  Temporary results during the calculations for
@@ -805,7 +813,12 @@ do_analyze_rel(Relation onerel, const VacuumParams params,
 			initStringInfo(&buf);
 
 			if (AmAutoVacuumWorkerProcess())
-				msgfmt = _("automatic analyze of table \"%s.%s.%s\"\n");
+			{
+				if (inh)
+					msgfmt = _("automatic analyze of table \"%s.%s.%s\" inheritance tree\n");
+				else
+					msgfmt = _("automatic analyze of table \"%s.%s.%s\"\n");
+			}
 			else
 				msgfmt = _("finished analyzing table \"%s.%s.%s\"\n");
 
@@ -813,6 +826,49 @@ do_analyze_rel(Relation onerel, const VacuumParams params,
 							 get_database_name(MyDatabaseId),
 							 get_namespace_name(RelationGetNamespace(onerel)),
 							 RelationGetRelationName(onerel));
+
+			/*
+			 * Report sampling statistics based on the table type.
+			 *
+			 * For foreign tables, we can only report the number of rows
+			 * sampled and estimated total, since sampling is done by the FDW.
+			 *
+			 * For inheritance trees and partitioned tables, we report
+			 * per-child sampling statistics collected during sampling.
+			 *
+			 * For regular tables, we report the standard sampling statistics.
+			 */
+			if (onerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+				appendStringInfo(&buf,
+								 _("sampling: target contains %.0f rows; %d rows in sample\n"),
+								 totalrows, numrows);
+			else if (inh && sampling_stats_list != NIL)
+			{
+				ListCell   *lc;
+
+				foreach(lc, sampling_stats_list)
+				{
+					AnalyzeSamplingStats *stats = (AnalyzeSamplingStats *) lfirst(lc);
+
+					appendStringInfo(&buf,
+									 _("sampling \"%s.%s\": scanned %u of %u pages, "
+									   "containing %.0f live rows and %.0f dead rows; "
+									   "%d rows in sample, %.0f estimated total rows\n"),
+									 get_namespace_name(get_rel_namespace(stats->relid)),
+									 get_rel_name(stats->relid),
+									 stats->scannedpages, stats->totalpages,
+									 stats->liverows, stats->deadrows,
+									 stats->samplerows, stats->totalrows);
+				}
+			}
+			else
+				appendStringInfo(&buf,
+								 _("sampling: scanned %u of %u pages, "
+								   "containing %.0f live rows and %.0f dead rows; "
+								   "%d rows in sample, %.0f estimated total rows\n"),
+								 sampling_stats.scannedpages, sampling_stats.totalpages,
+								 sampling_stats.liverows, sampling_stats.deadrows,
+								 sampling_stats.samplerows, sampling_stats.totalrows);
 			if (track_cost_delay_timing)
 			{
 				/*
@@ -1204,7 +1260,8 @@ block_sampling_read_stream_next(ReadStream *stream,
 static int
 acquire_sample_rows(Relation onerel, int elevel,
 					HeapTuple *rows, int targrows,
-					double *totalrows, double *totaldeadrows)
+					double *totalrows, double *totaldeadrows,
+					AnalyzeSamplingStats *sampling_stats)
 {
 	int			numrows = 0;	/* # rows now in reservoir */
 	double		samplerows = 0; /* total # rows collected */
@@ -1345,17 +1402,13 @@ acquire_sample_rows(Relation onerel, int elevel,
 		*totaldeadrows = 0.0;
 	}
 
-	/*
-	 * Emit some interesting relation info
-	 */
-	ereport(elevel,
-			(errmsg("\"%s\": scanned %d of %u pages, "
-					"containing %.0f live rows and %.0f dead rows; "
-					"%d rows in sample, %.0f estimated total rows",
-					RelationGetRelationName(onerel),
-					bs.m, totalblocks,
-					liverows, deadrows,
-					numrows, *totalrows)));
+	/* Populate sampling statistics output parameters */
+	sampling_stats->totalpages = totalblocks;
+	sampling_stats->scannedpages = bs.m;
+	sampling_stats->liverows = liverows;
+	sampling_stats->deadrows = deadrows;
+	sampling_stats->samplerows = numrows;
+	sampling_stats->totalrows = *totalrows;
 
 	return numrows;
 }
@@ -1396,7 +1449,8 @@ compare_rows(const void *a, const void *b, void *arg)
 static int
 acquire_inherited_sample_rows(Relation onerel, int elevel,
 							  HeapTuple *rows, int targrows,
-							  double *totalrows, double *totaldeadrows)
+							  double *totalrows, double *totaldeadrows,
+							  List **sampling_stats_list)
 {
 	List	   *tableOIDs;
 	Relation   *rels;
@@ -1412,6 +1466,7 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
 	/* Initialize output parameters to zero now, in case we exit early */
 	*totalrows = 0;
 	*totaldeadrows = 0;
+	*sampling_stats_list = NIL;
 
 	/*
 	 * Find all members of inheritance set.  We only need AccessShareLock on
@@ -1474,7 +1529,6 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
 			childrel->rd_rel->relkind == RELKIND_MATVIEW)
 		{
 			/* Regular table, so use the regular row acquisition function */
-			acquirefunc = acquire_sample_rows;
 			relpages = RelationGetNumberOfBlocks(childrel);
 		}
 		else if (childrel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
@@ -1586,9 +1640,29 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
 							tdrows;
 
 				/* Fetch a random sample of the child's rows */
-				childrows = (*acquirefunc) (childrel, elevel,
-											rows + numrows, childtargrows,
-											&trows, &tdrows);
+				if (childrel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+				{
+					childrows = (*acquirefunc) (childrel, elevel,
+												rows + numrows, childtargrows,
+												&trows, &tdrows);
+				}
+				else
+				{
+					AnalyzeSamplingStats *child_sampling_stats;
+
+					child_sampling_stats = (AnalyzeSamplingStats *)
+						palloc(sizeof(AnalyzeSamplingStats));
+
+					childrows = acquire_sample_rows(childrel, elevel,
+													rows + numrows, childtargrows,
+													&trows, &tdrows,
+													child_sampling_stats);
+
+					/* Set the relation OID and add to the list */
+					child_sampling_stats->relid = RelationGetRelid(childrel);
+					*sampling_stats_list = lappend(*sampling_stats_list,
+												   child_sampling_stats);
+				}
 
 				/* We may need to convert from child's rowtype to parent's */
 				if (childrows > 0 &&
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index e885a4b9c77..979b8088edb 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -300,6 +300,22 @@ typedef struct VacDeadItemsInfo
 	int64		num_items;		/* current # of entries */
 } VacDeadItemsInfo;
 
+/*
+ * AnalyzeSamplingStats stores sampling statistics collected during ANALYZE.
+ * This is used to report sampling information for both manual ANALYZE VERBOSE
+ * and autoanalyze logging.
+ */
+typedef struct AnalyzeSamplingStats
+{
+	Oid			relid;			/* relation OID */
+	BlockNumber totalpages;		/* total pages in relation */
+	BlockNumber scannedpages;	/* pages actually scanned */
+	double		liverows;		/* live rows found during sampling */
+	double		deadrows;		/* dead rows found during sampling */
+	int			samplerows;		/* number of rows in sample */
+	double		totalrows;		/* estimated total rows */
+} AnalyzeSamplingStats;
+
 /* GUC parameters */
 extern PGDLLIMPORT int default_statistics_target;	/* PGDLLIMPORT for PostGIS */
 extern PGDLLIMPORT int vacuum_freeze_min_age;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 3f3a888fd0e..6f3e875c59e 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -120,6 +120,7 @@ AmcheckOptions
 AnalyzeAttrComputeStatsFunc
 AnalyzeAttrFetchFunc
 AnalyzeForeignTable_function
+AnalyzeSamplingStats
 AnlExprData
 AnlIndexData
 AnyArrayType
-- 
2.34.1



^ permalink  raw  reply  [nested|flat] 6+ messages in thread

* Re: [PATCH] Add sampling statistics to autoanalyze log output
  2026-01-19 16:33 Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
@ 2026-02-10 15:18 ` Tatsuya Kawata <[email protected]>
  2026-02-12 02:49   ` Re: [PATCH] Add sampling statistics to autoanalyze log output Chao Li <[email protected]>
  0 siblings, 1 reply; 6+ messages in thread

From: Tatsuya Kawata @ 2026-02-10 15:18 UTC (permalink / raw)
  To: Fujii Masao <[email protected]>; +Cc: [email protected] <[email protected]>; Chao Li <[email protected]>; pgsql-hackers

Hi,

If anyone has had a chance to look at this patch and has any comments or
suggestions, I'd be more than happy to address them.
Thanks!

Regards,
Tatsuya Kawata


^ permalink  raw  reply  [nested|flat] 6+ messages in thread

* Re: [PATCH] Add sampling statistics to autoanalyze log output
  2026-01-19 16:33 Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
  2026-02-10 15:18 ` Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
@ 2026-02-12 02:49   ` Chao Li <[email protected]>
  2026-02-12 14:33     ` Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
  0 siblings, 1 reply; 6+ messages in thread

From: Chao Li @ 2026-02-12 02:49 UTC (permalink / raw)
  To: Tatsuya Kawata <[email protected]>; +Cc: Fujii Masao <[email protected]>; [email protected] <[email protected]>; pgsql-hackers



> On Feb 10, 2026, at 23:18, Tatsuya Kawata <[email protected]> wrote:
> 
> Hi,
> 
> If anyone has had a chance to look at this patch and has any comments or suggestions, I'd be more than happy to address them.
> Thanks!
> 
> Regards,
> Tatsuya Kawata

I reviewed v4, then applied it locally and played a little bit with it. I don’t have further comment.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/










^ permalink  raw  reply  [nested|flat] 6+ messages in thread

* Re: [PATCH] Add sampling statistics to autoanalyze log output
  2026-01-19 16:33 Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
  2026-02-10 15:18 ` Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
  2026-02-12 02:49   ` Re: [PATCH] Add sampling statistics to autoanalyze log output Chao Li <[email protected]>
@ 2026-02-12 14:33     ` Tatsuya Kawata <[email protected]>
  0 siblings, 0 replies; 6+ messages in thread

From: Tatsuya Kawata @ 2026-02-12 14:33 UTC (permalink / raw)
  To: Chao Li <[email protected]>; +Cc: Fujii Masao <[email protected]>; [email protected]; pgsql-hackers

Hi Chao-san,

Thank you for taking the time to review and test the patch!

Regards,
Tatsuya Kawata


^ permalink  raw  reply  [nested|flat] 6+ messages in thread

* [PATCH v38 05/11] Add Incremental View Maintenance support to psql
@ 2026-05-29 09:05 Yugo Nagata <[email protected]>
  0 siblings, 0 replies; 6+ messages in thread

From: Yugo Nagata @ 2026-05-29 09:05 UTC (permalink / raw)

Add tab completion and meta-command output for IVM.
---
 src/bin/psql/describe.c        | 32 +++++++++++++++++++++++++++++++-
 src/bin/psql/tab-complete.in.c | 30 ++++++++++++++++++------------
 2 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index af3935b0078..ad5c8274af0 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -1634,6 +1634,7 @@ describeOneTableDetails(const char *schemaname,
 		char		relpersistence;
 		char		relreplident;
 		char	   *relam;
+		bool		isivm;
 	}			tableinfo;
 	bool		show_column_details = false;
 
@@ -1648,7 +1649,26 @@ describeOneTableDetails(const char *schemaname,
 	/* Get general table info */
 	printfPQExpBuffer(&buf, "/* %s */\n",
 					  _("Get general information about one relation"));
-	if (pset.sversion >= 120000)
+	if (pset.sversion >= 200000)
+	{
+		printfPQExpBuffer(&buf,
+						  "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
+						  "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
+						  "false AS relhasoids, c.relispartition, %s, c.reltablespace, "
+						  "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
+						  "c.relpersistence, c.relreplident, am.amname, "
+						  "c.relisivm\n"
+						  "FROM pg_catalog.pg_class c\n "
+						  "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
+						  "LEFT JOIN pg_catalog.pg_am am ON (c.relam = am.oid)\n"
+						  "WHERE c.oid = '%s';",
+						  (verbose ?
+						   "pg_catalog.array_to_string(c.reloptions || "
+						   "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
+						   : "''"),
+						  oid);
+	}
+	else if (pset.sversion >= 120000)
 	{
 		appendPQExpBuffer(&buf,
 						  "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
@@ -1768,6 +1788,10 @@ describeOneTableDetails(const char *schemaname,
 			NULL : pg_strdup(PQgetvalue(res, 0, 14));
 	else
 		tableinfo.relam = NULL;
+	if (pset.sversion >= 200000)
+		tableinfo.isivm = strcmp(PQgetvalue(res, 0, 15), "t") == 0;
+	else
+		tableinfo.isivm = false;
 	PQclear(res);
 	res = NULL;
 
@@ -3830,6 +3854,12 @@ describeOneTableDetails(const char *schemaname,
 			printfPQExpBuffer(&buf, _("Access method: %s"), tableinfo.relam);
 			printTableAddFooter(&cont, buf.data);
 		}
+
+		/* Incremental view maintance info */
+		if (verbose && tableinfo.relkind == RELKIND_MATVIEW && tableinfo.isivm)
+		{
+			printTableAddFooter(&cont, _("Incremental view maintenance: yes"));
+		}
 	}
 
 	/* reloptions, if verbose */
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 46b9add0604..e5ef41710a0 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -1334,6 +1334,7 @@ static const pgsql_thing_t words_after_create[] = {
 	{"FOREIGN TABLE", NULL, NULL, NULL},
 	{"FUNCTION", NULL, NULL, Query_for_list_of_functions},
 	{"GROUP", Query_for_list_of_roles},
+	{"INCREMENTAL MATERIALIZED VIEW", NULL, NULL, &Query_for_list_of_matviews, NULL, THING_NO_DROP | THING_NO_ALTER},
 	{"INDEX", NULL, NULL, &Query_for_list_of_indexes},
 	{"LANGUAGE", Query_for_list_of_languages},
 	{"LARGE OBJECT", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
@@ -4256,28 +4257,33 @@ match_previous_words(int pattern_id,
 		COMPLETE_WITH("SELECT");
 
 /* CREATE MATERIALIZED VIEW */
-	else if (Matches("CREATE", "MATERIALIZED"))
+	else if (Matches("CREATE", "MATERIALIZED") ||
+			 Matches("CREATE", "INCREMENTAL", "MATERIALIZED"))
 		COMPLETE_WITH("VIEW");
-	/* Complete CREATE MATERIALIZED VIEW <name> with AS or USING */
-	else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny))
-		COMPLETE_WITH("AS", "USING");
 
+	/* Complete CREATE [INCREMENTAL] MATERIALIZED VIEW <name> with AS or USING */
+	else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny) ||
+			 Matches("CREATE", "INCREMENTAL", "MATERIALIZED", "VIEW", MatchAny))
+		COMPLETE_WITH("AS", "USING");
 	/*
-	 * Complete CREATE MATERIALIZED VIEW <name> USING with list of access
-	 * methods
+	 * Complete CREATE [INCREMENTAL] MATERIALIZED VIEW <name> USING with list
+	 * of access methods
 	 */
-	else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING"))
+	else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING") ||
+			 Matches("CREATE", "INCREMENTAL", "MATERIALIZED", "VIEW", MatchAny, "USING"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
-	/* Complete CREATE MATERIALIZED VIEW <name> USING <access method> with AS */
-	else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny))
+	/* Complete CREATE [INCREMENTAL] MATERIALIZED VIEW <name> USING <am> with AS */
+	else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny) ||
+			 Matches("CREATE", "INCREMENTAL", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny))
 		COMPLETE_WITH("AS");
-
 	/*
-	 * Complete CREATE MATERIALIZED VIEW <name> [USING <access method> ] AS
+	 * Complete CREATE [INCREMENTAL] MATERIALIZED VIEW <name> [USING <am>] AS
 	 * with "SELECT"
 	 */
 	else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS") ||
-			 Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny, "AS"))
+			 Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny, "AS") ||
+			 Matches("CREATE", "INCREMENTAL", "MATERIALIZED", "VIEW", MatchAny, "AS") ||
+			 Matches("CREATE", "INCREMENTAL", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny, "AS"))
 		COMPLETE_WITH("SELECT");
 
 /* CREATE EVENT TRIGGER */
-- 
2.43.0


--Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ
Content-Type: text/x-diff;
 name="v38-0004-Add-Incremental-View-Maintenance-support-to-pg_d.patch"
Content-Disposition: attachment;
 filename="v38-0004-Add-Incremental-View-Maintenance-support-to-pg_d.patch"
Content-Transfer-Encoding: 7bit



^ permalink  raw  reply  [nested|flat] 6+ messages in thread


end of thread, other threads:[~2026-05-29 09:05 UTC | newest]

Thread overview: 6+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2019-02-26 17:34 [PATCH v8 2/2] report (partial) progress of other index AMs Alvaro Herrera <[email protected]>
2026-01-19 16:33 Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
2026-02-10 15:18 ` Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
2026-02-12 02:49   ` Re: [PATCH] Add sampling statistics to autoanalyze log output Chao Li <[email protected]>
2026-02-12 14:33     ` Re: [PATCH] Add sampling statistics to autoanalyze log output Tatsuya Kawata <[email protected]>
2026-05-29 09:05 [PATCH v38 05/11] Add Incremental View Maintenance support to psql Yugo Nagata <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox