public inbox for [email protected]  
help / color / mirror / Atom feed
From: Drouvot, Bertrand <[email protected]>
To: Bharath Rupireddy <[email protected]>
Cc: Andres Freund <[email protected]>
Cc: Melanie Plageman <[email protected]>
Cc: PostgreSQL Hackers <[email protected]>
Subject: Re: Split index and table statistics into different types of stats
Date: Tue, 6 Dec 2022 20:11:08 +0100
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>
	<[email protected]>
	<[email protected]>
	<CAAKRu_asj8kSnukxHV764LTcUz5u-Z+iitjqesDB0yxthSm0Qw@mail.gmail.com>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<CALj2ACV4ndwRmcRXHAhLQ2XQCUSOh343O=AF_rH-a_NeN9LdoA@mail.gmail.com>
	<[email protected]>

Hi,

On 11/22/22 8:12 AM, Drouvot, Bertrand wrote:
> Hi,
> 
> On 11/22/22 7:19 AM, Bharath Rupireddy wrote:
>> On Mon, Nov 21, 2022 at 7:03 PM Drouvot, Bertrand
>> <[email protected]> wrote:
>>>
>>> On 11/21/22 12:19 AM, Andres Freund wrote:
>>>>
>>>> That's better, but still seems like quite a bit of repetition, given the
>>>> number of accessors. I think I like my idea of a macro defining the whole
>>>> function a bit better.
>>>>
>>>
>>> Got it, what about creating another preparatory commit to first introduce something like:
>>>
>>> "
>>> #define PGSTAT_DEFINE_REL_FIELD_ACCESSOR(function_name_prefix, stat_name) \
>>> Datum \
>>> function_name_prefix##_##stat_name(PG_FUNCTION_ARGS) \
>>> { \
>>> Oid                     relid = PG_GETARG_OID(0); \
>>> int64           result; \
>>> PgStat_StatTabEntry *tabentry; \
>>> if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) \
>>>          result = 0; \
>>> else \
>>>          result = (int64) (tabentry->stat_name); \
>>> PG_RETURN_INT64(result); \
>>> } \
>>>
>>> PGSTAT_DEFINE_REL_FIELD_ACCESSOR(pg_stat_get, numscans);
>>>
>>> PGSTAT_DEFINE_REL_FIELD_ACCESSOR(pg_stat_get, tuples_returned);
>>> .
>>> .
>>> .
>>> "
>>>
>>> If that makes sense to you, I'll submit this preparatory patch.
>>
>> I think the macros stitching the function declarations and definitions
>> is a great idea to avoid code duplicacy. We seem to be using that
>> approach already - PG_FUNCTION_INFO_V1, SH_DECLARE, SH_DEFINE and its
>> friends, STEMMER_MODULE and so on. +1 for first applying this
>> principle for existing functions. Looking forward to the patch.
>>
> 
> Thanks! Patch proposal submitted in [1].
> 
> I'll resume working on the current thread once [1] is committed.
> 
> [1]: https://www.postgresql.org/message-id/d547a9bc-76c2-f875-df74-3ad6fd9d6236%40gmail.com
> 

As [1] mentioned above has been committed (83a1a1b566), please find attached V5 related to this thread making use of the new macros (namely PG_STAT_GET_RELENTRY_INT64 and PG_STAT_GET_RELENTRY_TIMESTAMPTZ).

I switched from using "CppConcat" to using "##", as it looks to me it's easier to read now that we are adding another concatenation to the game (due to the table/index split).

The (Tab,tab) or (Ind,ind) passed as arguments to the macros look "weird" (I don't have a better idea yet): purpose is to follow the naming convention for PgStat_StatTabEntry/PgStat_StatIndEntry and pgstat_fetch_stat_tabentry/pgstat_fetch_stat_indentry, thoughts?

Looking forward to your feedback,

Regards,

-- 
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
diff --git a/src/backend/access/common/relation.c b/src/backend/access/common/relation.c
index 382a42ff7d..259bd06aed 100644
--- a/src/backend/access/common/relation.c
+++ b/src/backend/access/common/relation.c
@@ -73,7 +73,10 @@ relation_open(Oid relationId, LOCKMODE lockmode)
 	if (RelationUsesLocalBuffers(r))
 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
 
-	pgstat_init_relation(r);
+	if (r->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_init_index(r);
+	else
+		pgstat_init_table(r);
 
 	return r;
 }
@@ -123,7 +126,10 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
 	if (RelationUsesLocalBuffers(r))
 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
 
-	pgstat_init_relation(r);
+	if (r->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_init_index(r);
+	else
+		pgstat_init_table(r);
 
 	return r;
 }
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index dc303995e5..ceebc79302 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -590,7 +590,7 @@ index_fetch_heap(IndexScanDesc scan, TupleTableSlot *slot)
 									&scan->xs_heap_continue, &all_dead);
 
 	if (found)
-		pgstat_count_heap_fetch(scan->indexRelation);
+		pgstat_count_index_fetch(scan->indexRelation);
 
 	/*
 	 * If we scanned a whole HOT chain and found only dead tuples, tell index
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index bdd413f01b..d5b71fdd1e 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -404,7 +404,10 @@ heap_create(const char *relname,
 									 reltablespace);
 
 	/* ensure that stats are dropped if transaction aborts */
-	pgstat_create_relation(rel);
+	if (rel->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_create_index(rel);
+	else
+		pgstat_create_table(rel);
 
 	return rel;
 }
@@ -1853,7 +1856,7 @@ heap_drop_with_catalog(Oid relid)
 		RelationDropStorage(rel);
 
 	/* ensure that stats are dropped if transaction commits */
-	pgstat_drop_relation(rel);
+	pgstat_drop_table(rel);
 
 	/*
 	 * Close relcache entry, but *keep* AccessExclusiveLock on the relation
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 61f1d3926a..28b94fef7f 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1752,7 +1752,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
 	changeDependenciesOn(RelationRelationId, oldIndexId, newIndexId);
 
 	/* copy over statistics from old to new index */
-	pgstat_copy_relation_stats(newClassRel, oldClassRel);
+	pgstat_copy_index_stats(newClassRel, oldClassRel);
 
 	/* Copy data of pg_statistic from the old index to the new one */
 	CopyStatistics(oldIndexId, newIndexId);
@@ -2326,7 +2326,7 @@ index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode)
 		RelationDropStorage(userIndexRelation);
 
 	/* ensure that stats are dropped if transaction commits */
-	pgstat_drop_relation(userIndexRelation);
+	pgstat_drop_index(userIndexRelation);
 
 	/*
 	 * Close and flush the index's relcache entry, to ensure relcache doesn't
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 2d8104b090..a612ae81ed 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -655,29 +655,29 @@ CREATE VIEW pg_stat_all_tables AS
             C.oid AS relid,
             N.nspname AS schemaname,
             C.relname AS relname,
-            pg_stat_get_numscans(C.oid) AS seq_scan,
-            pg_stat_get_lastscan(C.oid) AS last_seq_scan,
-            pg_stat_get_tuples_returned(C.oid) AS seq_tup_read,
-            sum(pg_stat_get_numscans(I.indexrelid))::bigint AS idx_scan,
-            max(pg_stat_get_lastscan(I.indexrelid)) AS last_idx_scan,
-            sum(pg_stat_get_tuples_fetched(I.indexrelid))::bigint +
-            pg_stat_get_tuples_fetched(C.oid) AS idx_tup_fetch,
-            pg_stat_get_tuples_inserted(C.oid) AS n_tup_ins,
-            pg_stat_get_tuples_updated(C.oid) AS n_tup_upd,
-            pg_stat_get_tuples_deleted(C.oid) AS n_tup_del,
-            pg_stat_get_tuples_hot_updated(C.oid) AS n_tup_hot_upd,
-            pg_stat_get_live_tuples(C.oid) AS n_live_tup,
-            pg_stat_get_dead_tuples(C.oid) AS n_dead_tup,
-            pg_stat_get_mod_since_analyze(C.oid) AS n_mod_since_analyze,
-            pg_stat_get_ins_since_vacuum(C.oid) AS n_ins_since_vacuum,
-            pg_stat_get_last_vacuum_time(C.oid) as last_vacuum,
-            pg_stat_get_last_autovacuum_time(C.oid) as last_autovacuum,
-            pg_stat_get_last_analyze_time(C.oid) as last_analyze,
-            pg_stat_get_last_autoanalyze_time(C.oid) as last_autoanalyze,
-            pg_stat_get_vacuum_count(C.oid) AS vacuum_count,
-            pg_stat_get_autovacuum_count(C.oid) AS autovacuum_count,
-            pg_stat_get_analyze_count(C.oid) AS analyze_count,
-            pg_stat_get_autoanalyze_count(C.oid) AS autoanalyze_count
+            pg_stat_get_tab_numscans(C.oid) AS seq_scan,
+            pg_stat_get_tab_lastscan(C.oid) AS last_seq_scan,
+            pg_stat_get_tab_tuples_returned(C.oid) AS seq_tup_read,
+            sum(pg_stat_get_ind_numscans(I.indexrelid))::bigint AS idx_scan,
+            max(pg_stat_get_ind_lastscan(I.indexrelid)) AS last_idx_scan,
+            sum(pg_stat_get_ind_tuples_fetched(I.indexrelid))::bigint +
+            pg_stat_get_tab_tuples_fetched(C.oid) AS idx_tup_fetch,
+            pg_stat_get_tab_tuples_inserted(C.oid) AS n_tup_ins,
+            pg_stat_get_tab_tuples_updated(C.oid) AS n_tup_upd,
+            pg_stat_get_tab_tuples_deleted(C.oid) AS n_tup_del,
+            pg_stat_get_tab_tuples_hot_updated(C.oid) AS n_tup_hot_upd,
+            pg_stat_get_tab_live_tuples(C.oid) AS n_live_tup,
+            pg_stat_get_tab_dead_tuples(C.oid) AS n_dead_tup,
+            pg_stat_get_tab_mod_since_analyze(C.oid) AS n_mod_since_analyze,
+            pg_stat_get_tab_ins_since_vacuum(C.oid) AS n_ins_since_vacuum,
+            pg_stat_get_tab_last_vacuum_time(C.oid) as last_vacuum,
+            pg_stat_get_tab_last_autovacuum_time(C.oid) as last_autovacuum,
+            pg_stat_get_tab_last_analyze_time(C.oid) as last_analyze,
+            pg_stat_get_tab_last_autoanalyze_time(C.oid) as last_autoanalyze,
+            pg_stat_get_tab_vacuum_count(C.oid) AS vacuum_count,
+            pg_stat_get_tab_autovacuum_count(C.oid) AS autovacuum_count,
+            pg_stat_get_tab_analyze_count(C.oid) AS analyze_count,
+            pg_stat_get_tab_autoanalyze_count(C.oid) AS autoanalyze_count
     FROM pg_class C LEFT JOIN
          pg_index I ON C.oid = I.indrelid
          LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
@@ -689,9 +689,9 @@ CREATE VIEW pg_stat_xact_all_tables AS
             C.oid AS relid,
             N.nspname AS schemaname,
             C.relname AS relname,
-            pg_stat_get_xact_numscans(C.oid) AS seq_scan,
+            pg_stat_get_tab_xact_numscans(C.oid) AS seq_scan,
             pg_stat_get_xact_tuples_returned(C.oid) AS seq_tup_read,
-            sum(pg_stat_get_xact_numscans(I.indexrelid))::bigint AS idx_scan,
+            sum(pg_stat_get_ind_xact_numscans(I.indexrelid))::bigint AS idx_scan,
             sum(pg_stat_get_xact_tuples_fetched(I.indexrelid))::bigint +
             pg_stat_get_xact_tuples_fetched(C.oid) AS idx_tup_fetch,
             pg_stat_get_xact_tuples_inserted(C.oid) AS n_tup_ins,
@@ -729,31 +729,31 @@ CREATE VIEW pg_statio_all_tables AS
             C.oid AS relid,
             N.nspname AS schemaname,
             C.relname AS relname,
-            pg_stat_get_blocks_fetched(C.oid) -
-                    pg_stat_get_blocks_hit(C.oid) AS heap_blks_read,
-            pg_stat_get_blocks_hit(C.oid) AS heap_blks_hit,
+            pg_stat_get_tab_blocks_fetched(C.oid) -
+                    pg_stat_get_tab_blocks_hit(C.oid) AS heap_blks_read,
+            pg_stat_get_tab_blocks_hit(C.oid) AS heap_blks_hit,
             I.idx_blks_read AS idx_blks_read,
             I.idx_blks_hit AS idx_blks_hit,
-            pg_stat_get_blocks_fetched(T.oid) -
-                    pg_stat_get_blocks_hit(T.oid) AS toast_blks_read,
-            pg_stat_get_blocks_hit(T.oid) AS toast_blks_hit,
+            pg_stat_get_tab_blocks_fetched(T.oid) -
+                    pg_stat_get_tab_blocks_hit(T.oid) AS toast_blks_read,
+            pg_stat_get_tab_blocks_hit(T.oid) AS toast_blks_hit,
             X.idx_blks_read AS tidx_blks_read,
             X.idx_blks_hit AS tidx_blks_hit
     FROM pg_class C LEFT JOIN
             pg_class T ON C.reltoastrelid = T.oid
             LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
             LEFT JOIN LATERAL (
-              SELECT sum(pg_stat_get_blocks_fetched(indexrelid) -
-                         pg_stat_get_blocks_hit(indexrelid))::bigint
+              SELECT sum(pg_stat_get_ind_blocks_fetched(indexrelid) -
+                         pg_stat_get_ind_blocks_hit(indexrelid))::bigint
                      AS idx_blks_read,
-                     sum(pg_stat_get_blocks_hit(indexrelid))::bigint
+                     sum(pg_stat_get_ind_blocks_hit(indexrelid))::bigint
                      AS idx_blks_hit
               FROM pg_index WHERE indrelid = C.oid ) I ON true
             LEFT JOIN LATERAL (
-              SELECT sum(pg_stat_get_blocks_fetched(indexrelid) -
-                         pg_stat_get_blocks_hit(indexrelid))::bigint
+              SELECT sum(pg_stat_get_ind_blocks_fetched(indexrelid) -
+                         pg_stat_get_ind_blocks_hit(indexrelid))::bigint
                      AS idx_blks_read,
-                     sum(pg_stat_get_blocks_hit(indexrelid))::bigint
+                     sum(pg_stat_get_ind_blocks_hit(indexrelid))::bigint
                      AS idx_blks_hit
               FROM pg_index WHERE indrelid = T.oid ) X ON true
     WHERE C.relkind IN ('r', 't', 'm');
@@ -775,10 +775,10 @@ CREATE VIEW pg_stat_all_indexes AS
             N.nspname AS schemaname,
             C.relname AS relname,
             I.relname AS indexrelname,
-            pg_stat_get_numscans(I.oid) AS idx_scan,
-            pg_stat_get_lastscan(I.oid) AS last_idx_scan,
-            pg_stat_get_tuples_returned(I.oid) AS idx_tup_read,
-            pg_stat_get_tuples_fetched(I.oid) AS idx_tup_fetch
+            pg_stat_get_ind_numscans(I.oid) AS idx_scan,
+            pg_stat_get_ind_lastscan(I.oid) AS last_idx_scan,
+            pg_stat_get_ind_tuples_returned(I.oid) AS idx_tup_read,
+            pg_stat_get_ind_tuples_fetched(I.oid) AS idx_tup_fetch
     FROM pg_class C JOIN
             pg_index X ON C.oid = X.indrelid JOIN
             pg_class I ON I.oid = X.indexrelid
@@ -802,9 +802,9 @@ CREATE VIEW pg_statio_all_indexes AS
             N.nspname AS schemaname,
             C.relname AS relname,
             I.relname AS indexrelname,
-            pg_stat_get_blocks_fetched(I.oid) -
-                    pg_stat_get_blocks_hit(I.oid) AS idx_blks_read,
-            pg_stat_get_blocks_hit(I.oid) AS idx_blks_hit
+            pg_stat_get_ind_blocks_fetched(I.oid) -
+                    pg_stat_get_ind_blocks_hit(I.oid) AS idx_blks_read,
+            pg_stat_get_ind_blocks_hit(I.oid) AS idx_blks_hit
     FROM pg_class C JOIN
             pg_index X ON C.oid = X.indrelid JOIN
             pg_class I ON I.oid = X.indexrelid
@@ -826,9 +826,9 @@ CREATE VIEW pg_statio_all_sequences AS
             C.oid AS relid,
             N.nspname AS schemaname,
             C.relname AS relname,
-            pg_stat_get_blocks_fetched(C.oid) -
-                    pg_stat_get_blocks_hit(C.oid) AS blks_read,
-            pg_stat_get_blocks_hit(C.oid) AS blks_hit
+            pg_stat_get_ind_blocks_fetched(C.oid) -
+                    pg_stat_get_tab_blocks_hit(C.oid) AS blks_read,
+            pg_stat_get_tab_blocks_hit(C.oid) AS blks_hit
     FROM pg_class C
             LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
     WHERE C.relkind = 'S';
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 73d30bf619..f1a7a8aa8d 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -776,11 +776,19 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 	 * Read the buffer, and update pgstat counters to reflect a cache hit or
 	 * miss.
 	 */
-	pgstat_count_buffer_read(reln);
+	if (reln->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_count_index_buffer_read(reln);
+	else
+		pgstat_count_table_buffer_read(reln);
 	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
 							forkNum, blockNum, mode, strategy, &hit);
 	if (hit)
-		pgstat_count_buffer_hit(reln);
+	{
+		if (reln->rd_rel->relkind == RELKIND_INDEX)
+			pgstat_count_index_buffer_hit(reln);
+		else
+			pgstat_count_table_buffer_hit(reln);
+	}
 	return buf;
 }
 
diff --git a/src/backend/utils/activity/Makefile b/src/backend/utils/activity/Makefile
index a2e8507fd6..7441f4ce85 100644
--- a/src/backend/utils/activity/Makefile
+++ b/src/backend/utils/activity/Makefile
@@ -22,11 +22,12 @@ OBJS = \
 	pgstat_checkpointer.o \
 	pgstat_database.o \
 	pgstat_function.o \
-	pgstat_relation.o \
+	pgstat_index.o \
 	pgstat_replslot.o \
 	pgstat_shmem.o \
 	pgstat_slru.o \
 	pgstat_subscription.o \
+	pgstat_table.o \
 	pgstat_wal.o \
 	pgstat_xact.o \
 	wait_event.o
diff --git a/src/backend/utils/activity/meson.build b/src/backend/utils/activity/meson.build
index 5b3b558a67..e6bf3c59b6 100644
--- a/src/backend/utils/activity/meson.build
+++ b/src/backend/utils/activity/meson.build
@@ -7,11 +7,12 @@ backend_sources += files(
   'pgstat_checkpointer.c',
   'pgstat_database.c',
   'pgstat_function.c',
-  'pgstat_relation.c',
+  'pgstat_index.c',
   'pgstat_replslot.c',
   'pgstat_shmem.c',
   'pgstat_slru.c',
   'pgstat_subscription.c',
+  'pgstat_table.c',
   'pgstat_wal.c',
   'pgstat_xact.c',
   'wait_event.c',
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index 1ebe3bbf29..d49a5ea4bb 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -72,10 +72,11 @@
  * - pgstat_checkpointer.c
  * - pgstat_database.c
  * - pgstat_function.c
- * - pgstat_relation.c
+ * - pgstat_index.c
  * - pgstat_replslot.c
  * - pgstat_slru.c
  * - pgstat_subscription.c
+ * - pgstat_table.c
  * - pgstat_wal.c
  *
  * Whenever possible infrastructure files should not contain code related to
@@ -269,18 +270,32 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = {
 		.reset_timestamp_cb = pgstat_database_reset_timestamp_cb,
 	},
 
-	[PGSTAT_KIND_RELATION] = {
-		.name = "relation",
+	[PGSTAT_KIND_TABLE] = {
+		.name = "table",
 
 		.fixed_amount = false,
 
-		.shared_size = sizeof(PgStatShared_Relation),
-		.shared_data_off = offsetof(PgStatShared_Relation, stats),
-		.shared_data_len = sizeof(((PgStatShared_Relation *) 0)->stats),
+		.shared_size = sizeof(PgStatShared_Table),
+		.shared_data_off = offsetof(PgStatShared_Table, stats),
+		.shared_data_len = sizeof(((PgStatShared_Table *) 0)->stats),
 		.pending_size = sizeof(PgStat_TableStatus),
 
-		.flush_pending_cb = pgstat_relation_flush_cb,
-		.delete_pending_cb = pgstat_relation_delete_pending_cb,
+		.flush_pending_cb = pgstat_table_flush_cb,
+		.delete_pending_cb = pgstat_table_delete_pending_cb,
+	},
+
+	[PGSTAT_KIND_INDEX] = {
+		.name = "index",
+
+		.fixed_amount = false,
+
+		.shared_size = sizeof(PgStatShared_Index),
+		.shared_data_off = offsetof(PgStatShared_Index, stats),
+		.shared_data_len = sizeof(((PgStatShared_Index *) 0)->stats),
+		.pending_size = sizeof(PgStat_IndexStatus),
+
+		.flush_pending_cb = pgstat_index_flush_cb,
+		.delete_pending_cb = pgstat_index_delete_pending_cb,
 	},
 
 	[PGSTAT_KIND_FUNCTION] = {
diff --git a/src/backend/utils/activity/pgstat_index.c b/src/backend/utils/activity/pgstat_index.c
new file mode 100644
index 0000000000..13b48b11e5
--- /dev/null
+++ b/src/backend/utils/activity/pgstat_index.c
@@ -0,0 +1,297 @@
+/* -------------------------------------------------------------------------
+ *
+ * pgstat_index.c
+ *	  Implementation of index statistics.
+ *
+ * This file contains the implementation of function index. It is kept
+ * separate from pgstat.c to enforce the line between the statistics access /
+ * storage implementation and the details about individual types of
+ * statistics.
+ *
+ * Copyright (c) 2001-2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/backend/utils/activity/pgstat_index.c
+ * -------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/xact.h"
+#include "utils/pgstat_internal.h"
+#include "utils/rel.h"
+#include "catalog/catalog.h"
+
+static PgStat_IndexStatus *pgstat_prep_index_pending(Oid rel_id, bool isshared);
+
+/*
+ * Copy stats between indexes. This is used for things like REINDEX
+ * CONCURRENTLY.
+ */
+void
+pgstat_copy_index_stats(Relation dst, Relation src)
+{
+	PgStat_StatIndEntry *srcstats;
+	PgStatShared_Index *dstshstats;
+	PgStat_EntryRef *dst_ref;
+
+	srcstats = pgstat_fetch_stat_indentry_ext(src->rd_rel->relisshared,
+											  RelationGetRelid(src));
+	if (!srcstats)
+		return;
+
+	dst_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_INDEX,
+										  dst->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
+										  RelationGetRelid(dst),
+										  false);
+
+	dstshstats = (PgStatShared_Index *) dst_ref->shared_stats;
+	dstshstats->stats = *srcstats;
+
+	pgstat_unlock_entry(dst_ref);
+}
+
+/*
+ * Initialize a relcache entry to count access statistics.  Called whenever an
+ * index is opened.
+ *
+ * We assume that a relcache entry's pgstatind_info field is zeroed by relcache.c
+ * when the relcache entry is made; thereafter it is long-lived data.
+ *
+ * This does not create a reference to a stats entry in shared memory, nor
+ * allocate memory for the pending stats. That happens in
+ * pgstat_assoc_index().
+ */
+void
+pgstat_init_index(Relation rel)
+{
+	/*
+	 * We only count stats for indexes
+	 */
+	Assert(rel->rd_rel->relkind == RELKIND_INDEX);
+
+	if (!pgstat_track_counts)
+	{
+		if (rel->pgstatind_info != NULL)
+			pgstat_unlink_index(rel);
+
+		/* We're not counting at all */
+		rel->pgstat_enabled = false;
+		rel->pgstatind_info = NULL;
+		return;
+	}
+
+	rel->pgstat_enabled = true;
+}
+
+/*
+ * Prepare for statistics for this index to be collected.
+ *
+ * This ensures we have a reference to the stats entry before stats can be
+ * generated. That is important because an index drop in another
+ * connection could otherwise lead to the stats entry being dropped, which then
+ * later would get recreated when flushing stats.
+ *
+ * This is separate from pgstat_init_index() as it is not uncommon for
+ * relcache entries to be opened without ever getting stats reported.
+ */
+void
+pgstat_assoc_index(Relation rel)
+{
+	Assert(rel->pgstat_enabled);
+	Assert(rel->pgstatind_info == NULL);
+
+	/* Else find or make the PgStat_IndexStatus entry, and update link */
+	rel->pgstatind_info = pgstat_prep_index_pending(RelationGetRelid(rel),
+													rel->rd_rel->relisshared);
+
+	/* don't allow link a stats to multiple relcache entries */
+	Assert(rel->pgstatind_info->relation == NULL);
+
+	/* mark this relation as the owner */
+	rel->pgstatind_info->relation = rel;
+}
+
+/*
+ * Break the mutual link between a relcache entry and pending index stats entry.
+ * This must be called whenever one end of the link is removed.
+ */
+void
+pgstat_unlink_index(Relation rel)
+{
+
+	if (rel->pgstatind_info == NULL)
+		return;
+
+	/* link sanity check for the index stats */
+	if (rel->pgstatind_info)
+	{
+		Assert(rel->pgstatind_info->relation == rel);
+		rel->pgstatind_info->relation = NULL;
+		rel->pgstatind_info = NULL;
+	}
+}
+
+/*
+ * Ensure that index stats are dropped if transaction aborts.
+ */
+void
+pgstat_create_index(Relation rel)
+{
+	pgstat_create_transactional(PGSTAT_KIND_INDEX,
+								rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
+								RelationGetRelid(rel));
+}
+
+/*
+ * Ensure that index stats are dropped if transaction commits.
+ */
+void
+pgstat_drop_index(Relation rel)
+{
+	pgstat_drop_transactional(PGSTAT_KIND_INDEX,
+							  rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
+							  RelationGetRelid(rel));
+}
+
+/*
+ * Support function for the SQL-callable pgstat* functions. Returns
+ * the collected statistics for one index or NULL. NULL doesn't mean
+ * that the index doesn't exist, just that there are no statistics, so the
+ * caller is better off to report ZERO instead.
+ */
+PgStat_StatIndEntry *
+pgstat_fetch_stat_indentry(Oid relid)
+{
+	return pgstat_fetch_stat_indentry_ext(IsSharedRelation(relid), relid);
+}
+
+/*
+ * More efficient version of pgstat_fetch_stat_indentry(), allowing to specify
+ * whether the to-be-accessed index is shared or not.
+ */
+PgStat_StatIndEntry *
+pgstat_fetch_stat_indentry_ext(bool shared, Oid reloid)
+{
+	Oid			dboid = (shared ? InvalidOid : MyDatabaseId);
+
+	return (PgStat_StatIndEntry *)
+		pgstat_fetch_entry(PGSTAT_KIND_INDEX, dboid, reloid);
+}
+
+/*
+ * find any existing PgStat_IndexStatus entry for rel
+ *
+ * Find any existing PgStat_IndexStatus entry for rel_id in the current
+ * database. If not found, try finding from shared indexes.
+ *
+ * If no entry found, return NULL, don't create a new one
+ */
+PgStat_IndexStatus *
+find_indstat_entry(Oid rel_id)
+{
+	PgStat_EntryRef *entry_ref;
+
+	entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_INDEX, MyDatabaseId, rel_id);
+	if (!entry_ref)
+		entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_INDEX, InvalidOid, rel_id);
+
+	if (entry_ref)
+		return entry_ref->pending;
+	return NULL;
+}
+
+/*
+ * Flush out pending stats for the entry
+ *
+ * If nowait is true, this function returns false if lock could not
+ * immediately acquired, otherwise true is returned.
+ *
+ * Some of the stats are copied to the corresponding pending database stats
+ * entry when successfully flushing.
+ */
+bool
+pgstat_index_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
+{
+	static const PgStat_IndexCounts all_zeroes;
+	Oid			dboid;
+
+	PgStat_IndexStatus *lstats; /* pending stats entry  */
+	PgStatShared_Index *shrelcomstats;
+	PgStat_StatIndEntry *indentry;	/* index entry of shared stats */
+	PgStat_StatDBEntry *dbentry;	/* pending database entry */
+
+	dboid = entry_ref->shared_entry->key.dboid;
+	lstats = (PgStat_IndexStatus *) entry_ref->pending;
+	shrelcomstats = (PgStatShared_Index *) entry_ref->shared_stats;
+
+	/*
+	 * Ignore entries that didn't accumulate any actual counts, such as
+	 * indexes that were opened by the planner but not used.
+	 */
+	if (memcmp(&lstats->i_counts, &all_zeroes,
+			   sizeof(PgStat_IndexCounts)) == 0)
+	{
+		return true;
+	}
+
+	if (!pgstat_lock_entry(entry_ref, nowait))
+		return false;
+
+	/* add the values to the shared entry. */
+	indentry = &shrelcomstats->stats;
+
+	indentry->numscans += lstats->i_counts.i_numscans;
+
+	if (lstats->i_counts.i_numscans)
+	{
+		TimestampTz t = GetCurrentTransactionStopTimestamp();
+
+		if (t > indentry->lastscan)
+			indentry->lastscan = t;
+	}
+	indentry->tuples_returned += lstats->i_counts.i_tuples_returned;
+	indentry->tuples_fetched += lstats->i_counts.i_tuples_fetched;
+	indentry->blocks_fetched += lstats->i_counts.i_blocks_fetched;
+	indentry->blocks_hit += lstats->i_counts.i_blocks_hit;
+
+	pgstat_unlock_entry(entry_ref);
+
+	/* The entry was successfully flushed, add the same to database stats */
+	dbentry = pgstat_prep_database_pending(dboid);
+	dbentry->n_tuples_returned += lstats->i_counts.i_tuples_returned;
+	dbentry->n_tuples_fetched += lstats->i_counts.i_tuples_fetched;
+	dbentry->n_blocks_fetched += lstats->i_counts.i_blocks_fetched;
+	dbentry->n_blocks_hit += lstats->i_counts.i_blocks_hit;
+
+	return true;
+}
+
+void
+pgstat_index_delete_pending_cb(PgStat_EntryRef *entry_ref)
+{
+	PgStat_IndexStatus *pending = (PgStat_IndexStatus *) entry_ref->pending;
+
+	if (pending->relation)
+		pgstat_unlink_index(pending->relation);
+}
+
+/*
+ * Find or create a PgStat_IndexStatus entry for rel. New entry is created and
+ * initialized if not exists.
+ */
+static PgStat_IndexStatus *
+pgstat_prep_index_pending(Oid rel_id, bool isshared)
+{
+	PgStat_EntryRef *entry_ref;
+	PgStat_IndexStatus *pending;
+
+	entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_INDEX,
+										  isshared ? InvalidOid : MyDatabaseId,
+										  rel_id, NULL);
+	pending = entry_ref->pending;
+	pending->r_id = rel_id;
+	pending->r_shared = isshared;
+
+	return pending;
+}
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_table.c
similarity index 75%
rename from src/backend/utils/activity/pgstat_relation.c
rename to src/backend/utils/activity/pgstat_table.c
index a9c05153d9..b9c29bd7c2 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_table.c
@@ -1,9 +1,9 @@
 /* -------------------------------------------------------------------------
  *
- * pgstat_relation.c
- *	  Implementation of relation statistics.
+ * pgstat_table.c
+ *	  Implementation of table statistics.
  *
- * This file contains the implementation of function relation. It is kept
+ * This file contains the implementation of function table. It is kept
  * separate from pgstat.c to enforce the line between the statistics access /
  * storage implementation and the details about individual types of
  * statistics.
@@ -11,7 +11,7 @@
  * Copyright (c) 2001-2022, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  src/backend/utils/activity/pgstat_relation.c
+ *	  src/backend/utils/activity/pgstat_table.c
  * -------------------------------------------------------------------------
  */
 
@@ -44,74 +44,48 @@ typedef struct TwoPhasePgStatRecord
 } TwoPhasePgStatRecord;
 
 
-static PgStat_TableStatus *pgstat_prep_relation_pending(Oid rel_id, bool isshared);
-static void add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level);
-static void ensure_tabstat_xact_level(PgStat_TableStatus *pgstat_info);
+static PgStat_TableStatus *pgstat_prep_table_pending(Oid rel_id, bool isshared);
+static void add_tabstat_xact_level(PgStat_TableStatus *pgstattab_info, int nest_level);
+static void ensure_tabstat_xact_level(PgStat_TableStatus *pgstattab_info);
 static void save_truncdrop_counters(PgStat_TableXactStatus *trans, bool is_drop);
 static void restore_truncdrop_counters(PgStat_TableXactStatus *trans);
 
-
-/*
- * Copy stats between relations. This is used for things like REINDEX
- * CONCURRENTLY.
- */
-void
-pgstat_copy_relation_stats(Relation dst, Relation src)
-{
-	PgStat_StatTabEntry *srcstats;
-	PgStatShared_Relation *dstshstats;
-	PgStat_EntryRef *dst_ref;
-
-	srcstats = pgstat_fetch_stat_tabentry_ext(src->rd_rel->relisshared,
-											  RelationGetRelid(src));
-	if (!srcstats)
-		return;
-
-	dst_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION,
-										  dst->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
-										  RelationGetRelid(dst),
-										  false);
-
-	dstshstats = (PgStatShared_Relation *) dst_ref->shared_stats;
-	dstshstats->stats = *srcstats;
-
-	pgstat_unlock_entry(dst_ref);
-}
-
 /*
  * Initialize a relcache entry to count access statistics.  Called whenever a
- * relation is opened.
+ * table is opened.
  *
- * We assume that a relcache entry's pgstat_info field is zeroed by relcache.c
+ * We assume that a relcache entry's pgstattab_info field is zeroed by relcache.c
  * when the relcache entry is made; thereafter it is long-lived data.
  *
  * This does not create a reference to a stats entry in shared memory, nor
  * allocate memory for the pending stats. That happens in
- * pgstat_assoc_relation().
+ * pgstat_assoc_table().
  */
 void
-pgstat_init_relation(Relation rel)
+pgstat_init_table(Relation rel)
 {
 	char		relkind = rel->rd_rel->relkind;
 
+	Assert(relkind != RELKIND_INDEX);
+
 	/*
 	 * We only count stats for relations with storage and partitioned tables
 	 */
 	if (!RELKIND_HAS_STORAGE(relkind) && relkind != RELKIND_PARTITIONED_TABLE)
 	{
 		rel->pgstat_enabled = false;
-		rel->pgstat_info = NULL;
+		rel->pgstattab_info = NULL;
 		return;
 	}
 
 	if (!pgstat_track_counts)
 	{
-		if (rel->pgstat_info)
-			pgstat_unlink_relation(rel);
+		if (rel->pgstattab_info != NULL)
+			pgstat_unlink_table(rel);
 
 		/* We're not counting at all */
 		rel->pgstat_enabled = false;
-		rel->pgstat_info = NULL;
+		rel->pgstattab_info = NULL;
 		return;
 	}
 
@@ -119,89 +93,92 @@ pgstat_init_relation(Relation rel)
 }
 
 /*
- * Prepare for statistics for this relation to be collected.
+ * Prepare for statistics for this table to be collected.
  *
  * This ensures we have a reference to the stats entry before stats can be
- * generated. That is important because a relation drop in another connection
+ * generated. That is important because a table drop in another connection
  * could otherwise lead to the stats entry being dropped, which then later
  * would get recreated when flushing stats.
  *
- * This is separate from pgstat_init_relation() as it is not uncommon for
+ * This is separate from pgstat_init_table() as it is not uncommon for
  * relcache entries to be opened without ever getting stats reported.
  */
 void
-pgstat_assoc_relation(Relation rel)
+pgstat_assoc_table(Relation rel)
 {
 	Assert(rel->pgstat_enabled);
-	Assert(rel->pgstat_info == NULL);
+	Assert(rel->pgstattab_info == NULL);
 
 	/* Else find or make the PgStat_TableStatus entry, and update link */
-	rel->pgstat_info = pgstat_prep_relation_pending(RelationGetRelid(rel),
+	rel->pgstattab_info = pgstat_prep_table_pending(RelationGetRelid(rel),
 													rel->rd_rel->relisshared);
 
 	/* don't allow link a stats to multiple relcache entries */
-	Assert(rel->pgstat_info->relation == NULL);
+	Assert(rel->pgstattab_info->relation == NULL);
 
 	/* mark this relation as the owner */
-	rel->pgstat_info->relation = rel;
+	rel->pgstattab_info->relation = rel;
 }
 
 /*
- * Break the mutual link between a relcache entry and pending stats entry.
+ * Break the mutual link between a relcache entry and pending table stats entry.
  * This must be called whenever one end of the link is removed.
  */
 void
-pgstat_unlink_relation(Relation rel)
+pgstat_unlink_table(Relation rel)
 {
-	/* remove the link to stats info if any */
-	if (rel->pgstat_info == NULL)
+
+	if (rel->pgstattab_info == NULL)
 		return;
 
-	/* link sanity check */
-	Assert(rel->pgstat_info->relation == rel);
-	rel->pgstat_info->relation = NULL;
-	rel->pgstat_info = NULL;
+	/* link sanity check for the table stats */
+	if (rel->pgstattab_info)
+	{
+		Assert(rel->pgstattab_info->relation == rel);
+		rel->pgstattab_info->relation = NULL;
+		rel->pgstattab_info = NULL;
+	}
 }
 
 /*
- * Ensure that stats are dropped if transaction aborts.
+ * Ensure that table stats are dropped if transaction aborts.
  */
 void
-pgstat_create_relation(Relation rel)
+pgstat_create_table(Relation rel)
 {
-	pgstat_create_transactional(PGSTAT_KIND_RELATION,
+	pgstat_create_transactional(PGSTAT_KIND_TABLE,
 								rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
 								RelationGetRelid(rel));
 }
 
 /*
- * Ensure that stats are dropped if transaction commits.
+ * Ensure that table stats are dropped if transaction commits.
  */
 void
-pgstat_drop_relation(Relation rel)
+pgstat_drop_table(Relation rel)
 {
 	int			nest_level = GetCurrentTransactionNestLevel();
-	PgStat_TableStatus *pgstat_info;
+	PgStat_TableStatus *pgstattab_info;
 
-	pgstat_drop_transactional(PGSTAT_KIND_RELATION,
+	pgstat_drop_transactional(PGSTAT_KIND_TABLE,
 							  rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
 							  RelationGetRelid(rel));
 
-	if (!pgstat_should_count_relation(rel))
+	if (!pgstat_should_count_table(rel))
 		return;
 
 	/*
 	 * Transactionally set counters to 0. That ensures that accesses to
 	 * pg_stat_xact_all_tables inside the transaction show 0.
 	 */
-	pgstat_info = rel->pgstat_info;
-	if (pgstat_info->trans &&
-		pgstat_info->trans->nest_level == nest_level)
+	pgstattab_info = rel->pgstattab_info;
+	if (pgstattab_info->trans &&
+		pgstattab_info->trans->nest_level == nest_level)
 	{
-		save_truncdrop_counters(pgstat_info->trans, true);
-		pgstat_info->trans->tuples_inserted = 0;
-		pgstat_info->trans->tuples_updated = 0;
-		pgstat_info->trans->tuples_deleted = 0;
+		save_truncdrop_counters(pgstattab_info->trans, true);
+		pgstattab_info->trans->tuples_inserted = 0;
+		pgstattab_info->trans->tuples_updated = 0;
+		pgstattab_info->trans->tuples_deleted = 0;
 	}
 }
 
@@ -213,7 +190,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 					 PgStat_Counter livetuples, PgStat_Counter deadtuples)
 {
 	PgStat_EntryRef *entry_ref;
-	PgStatShared_Relation *shtabentry;
+	PgStatShared_Table *shtabentry;
 	PgStat_StatTabEntry *tabentry;
 	Oid			dboid = (shared ? InvalidOid : MyDatabaseId);
 	TimestampTz ts;
@@ -225,10 +202,10 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	ts = GetCurrentTimestamp();
 
 	/* block acquiring lock for the same reason as pgstat_report_autovac() */
-	entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION,
+	entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_TABLE,
 											dboid, tableoid, false);
 
-	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
+	shtabentry = (PgStatShared_Table *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
 	tabentry->live_tuples = livetuples;
@@ -272,7 +249,7 @@ pgstat_report_analyze(Relation rel,
 					  bool resetcounter)
 {
 	PgStat_EntryRef *entry_ref;
-	PgStatShared_Relation *shtabentry;
+	PgStatShared_Table *shtabentry;
 	PgStat_StatTabEntry *tabentry;
 	Oid			dboid = (rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId);
 
@@ -291,31 +268,31 @@ pgstat_report_analyze(Relation rel,
 	 *
 	 * Waste no time on partitioned tables, though.
 	 */
-	if (pgstat_should_count_relation(rel) &&
+	if (pgstat_should_count_table(rel) &&
 		rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
 	{
 		PgStat_TableXactStatus *trans;
 
-		for (trans = rel->pgstat_info->trans; trans; trans = trans->upper)
+		for (trans = rel->pgstattab_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;
+		deadtuples -= rel->pgstattab_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);
 	}
 
 	/* block acquiring lock for the same reason as pgstat_report_autovac() */
-	entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION, dboid,
+	entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_TABLE, dboid,
 											RelationGetRelid(rel),
 											false);
 	/* can't get dropped while accessed */
 	Assert(entry_ref != NULL && entry_ref->shared_stats != NULL);
 
-	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
+	shtabentry = (PgStatShared_Table *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
 	tabentry->live_tuples = livetuples;
@@ -349,12 +326,12 @@ pgstat_report_analyze(Relation rel,
 void
 pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		ensure_tabstat_xact_level(pgstat_info);
-		pgstat_info->trans->tuples_inserted += n;
+		ensure_tabstat_xact_level(pgstattab_info);
+		pgstattab_info->trans->tuples_inserted += n;
 	}
 }
 
@@ -364,16 +341,16 @@ pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
 void
 pgstat_count_heap_update(Relation rel, bool hot)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		ensure_tabstat_xact_level(pgstat_info);
-		pgstat_info->trans->tuples_updated++;
+		ensure_tabstat_xact_level(pgstattab_info);
+		pgstattab_info->trans->tuples_updated++;
 
 		/* t_tuples_hot_updated is nontransactional, so just advance it */
 		if (hot)
-			pgstat_info->t_counts.t_tuples_hot_updated++;
+			pgstattab_info->t_counts.t_tuples_hot_updated++;
 	}
 }
 
@@ -383,12 +360,12 @@ pgstat_count_heap_update(Relation rel, bool hot)
 void
 pgstat_count_heap_delete(Relation rel)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		ensure_tabstat_xact_level(pgstat_info);
-		pgstat_info->trans->tuples_deleted++;
+		ensure_tabstat_xact_level(pgstattab_info);
+		pgstattab_info->trans->tuples_deleted++;
 	}
 }
 
@@ -398,15 +375,15 @@ pgstat_count_heap_delete(Relation rel)
 void
 pgstat_count_truncate(Relation rel)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		ensure_tabstat_xact_level(pgstat_info);
-		save_truncdrop_counters(pgstat_info->trans, false);
-		pgstat_info->trans->tuples_inserted = 0;
-		pgstat_info->trans->tuples_updated = 0;
-		pgstat_info->trans->tuples_deleted = 0;
+		ensure_tabstat_xact_level(pgstattab_info);
+		save_truncdrop_counters(pgstattab_info->trans, false);
+		pgstattab_info->trans->tuples_inserted = 0;
+		pgstattab_info->trans->tuples_updated = 0;
+		pgstattab_info->trans->tuples_deleted = 0;
 	}
 }
 
@@ -421,11 +398,11 @@ pgstat_count_truncate(Relation rel)
 void
 pgstat_update_heap_dead_tuples(Relation rel, int delta)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		pgstat_info->t_counts.t_delta_dead_tuples -= delta;
+		pgstattab_info->t_counts.t_delta_dead_tuples -= delta;
 	}
 }
 
@@ -451,7 +428,7 @@ pgstat_fetch_stat_tabentry_ext(bool shared, Oid reloid)
 	Oid			dboid = (shared ? InvalidOid : MyDatabaseId);
 
 	return (PgStat_StatTabEntry *)
-		pgstat_fetch_entry(PGSTAT_KIND_RELATION, dboid, reloid);
+		pgstat_fetch_entry(PGSTAT_KIND_TABLE, dboid, reloid);
 }
 
 /*
@@ -467,9 +444,9 @@ find_tabstat_entry(Oid rel_id)
 {
 	PgStat_EntryRef *entry_ref;
 
-	entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, MyDatabaseId, rel_id);
+	entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_TABLE, MyDatabaseId, rel_id);
 	if (!entry_ref)
-		entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, InvalidOid, rel_id);
+		entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_TABLE, InvalidOid, rel_id);
 
 	if (entry_ref)
 		return entry_ref->pending;
@@ -477,7 +454,7 @@ find_tabstat_entry(Oid rel_id)
 }
 
 /*
- * Perform relation stats specific end-of-transaction work. Helper for
+ * Perform table stats specific end-of-transaction work. Helper for
  * AtEOXact_PgStat.
  *
  * Transfer transactional insert/update counts into the base tabstat entries.
@@ -485,7 +462,7 @@ find_tabstat_entry(Oid rel_id)
  * TopTransactionContext and will go away anyway.
  */
 void
-AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit)
+AtEOXact_PgStat_Tables(PgStat_SubXactStatus *xact_state, bool isCommit)
 {
 	PgStat_TableXactStatus *trans;
 
@@ -536,14 +513,14 @@ AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit)
 }
 
 /*
- * Perform relation stats specific end-of-sub-transaction work. Helper for
+ * Perform table stats specific end-of-sub-transaction work. Helper for
  * AtEOSubXact_PgStat.
  *
  * Transfer transactional insert/update counts into the next higher
  * subtransaction state.
  */
 void
-AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth)
+AtEOSubXact_PgStat_Tables(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth)
 {
 	PgStat_TableXactStatus *trans;
 	PgStat_TableXactStatus *next_trans;
@@ -620,11 +597,11 @@ AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, in
 }
 
 /*
- * Generate 2PC records for all the pending transaction-dependent relation
+ * Generate 2PC records for all the pending transaction-dependent table
  * stats.
  */
 void
-AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
+AtPrepare_PgStat_Tables(PgStat_SubXactStatus *xact_state)
 {
 	PgStat_TableXactStatus *trans;
 
@@ -659,10 +636,10 @@ AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
  * reported to the stats system immediately, while the effects on live and
  * dead tuple counts are preserved in the 2PC state file.
  *
- * Note: AtEOXact_PgStat_Relations is not called during PREPARE.
+ * Note: AtEOXact_PgStat_Tables is not called during PREPARE.
  */
 void
-PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
+PostPrepare_PgStat_Tables(PgStat_SubXactStatus *xact_state)
 {
 	PgStat_TableXactStatus *trans;
 
@@ -685,27 +662,27 @@ pgstat_twophase_postcommit(TransactionId xid, uint16 info,
 						   void *recdata, uint32 len)
 {
 	TwoPhasePgStatRecord *rec = (TwoPhasePgStatRecord *) recdata;
-	PgStat_TableStatus *pgstat_info;
+	PgStat_TableStatus *pgstattab_info;
 
 	/* Find or create a tabstat entry for the rel */
-	pgstat_info = pgstat_prep_relation_pending(rec->t_id, rec->t_shared);
+	pgstattab_info = pgstat_prep_table_pending(rec->t_id, rec->t_shared);
 
 	/* Same math as in AtEOXact_PgStat, commit case */
-	pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
-	pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated;
-	pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
-	pgstat_info->t_counts.t_truncdropped = rec->t_truncdropped;
+	pgstattab_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
+	pgstattab_info->t_counts.t_tuples_updated += rec->tuples_updated;
+	pgstattab_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
+	pgstattab_info->t_counts.t_truncdropped = rec->t_truncdropped;
 	if (rec->t_truncdropped)
 	{
 		/* forget live/dead stats seen by backend thus far */
-		pgstat_info->t_counts.t_delta_live_tuples = 0;
-		pgstat_info->t_counts.t_delta_dead_tuples = 0;
+		pgstattab_info->t_counts.t_delta_live_tuples = 0;
+		pgstattab_info->t_counts.t_delta_dead_tuples = 0;
 	}
-	pgstat_info->t_counts.t_delta_live_tuples +=
+	pgstattab_info->t_counts.t_delta_live_tuples +=
 		rec->tuples_inserted - rec->tuples_deleted;
-	pgstat_info->t_counts.t_delta_dead_tuples +=
+	pgstattab_info->t_counts.t_delta_dead_tuples +=
 		rec->tuples_updated + rec->tuples_deleted;
-	pgstat_info->t_counts.t_changed_tuples +=
+	pgstattab_info->t_counts.t_changed_tuples +=
 		rec->tuples_inserted + rec->tuples_updated +
 		rec->tuples_deleted;
 }
@@ -721,10 +698,10 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info,
 						  void *recdata, uint32 len)
 {
 	TwoPhasePgStatRecord *rec = (TwoPhasePgStatRecord *) recdata;
-	PgStat_TableStatus *pgstat_info;
+	PgStat_TableStatus *pgstattab_info;
 
 	/* Find or create a tabstat entry for the rel */
-	pgstat_info = pgstat_prep_relation_pending(rec->t_id, rec->t_shared);
+	pgstattab_info = pgstat_prep_table_pending(rec->t_id, rec->t_shared);
 
 	/* Same math as in AtEOXact_PgStat, abort case */
 	if (rec->t_truncdropped)
@@ -733,10 +710,10 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info,
 		rec->tuples_updated = rec->updated_pre_truncdrop;
 		rec->tuples_deleted = rec->deleted_pre_truncdrop;
 	}
-	pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
-	pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated;
-	pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
-	pgstat_info->t_counts.t_delta_dead_tuples +=
+	pgstattab_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
+	pgstattab_info->t_counts.t_tuples_updated += rec->tuples_updated;
+	pgstattab_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
+	pgstattab_info->t_counts.t_delta_dead_tuples +=
 		rec->tuples_inserted + rec->tuples_updated;
 }
 
@@ -750,22 +727,21 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info,
  * entry when successfully flushing.
  */
 bool
-pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
+pgstat_table_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 {
 	static const PgStat_TableCounts all_zeroes;
 	Oid			dboid;
 	PgStat_TableStatus *lstats; /* pending stats entry  */
-	PgStatShared_Relation *shtabstats;
+	PgStatShared_Table *shtabstats;
 	PgStat_StatTabEntry *tabentry;	/* table entry of shared stats */
 	PgStat_StatDBEntry *dbentry;	/* pending database entry */
 
 	dboid = entry_ref->shared_entry->key.dboid;
 	lstats = (PgStat_TableStatus *) entry_ref->pending;
-	shtabstats = (PgStatShared_Relation *) entry_ref->shared_stats;
+	shtabstats = (PgStatShared_Table *) entry_ref->shared_stats;
 
 	/*
-	 * Ignore entries that didn't accumulate any actual counts, such as
-	 * indexes that were opened by the planner but not used.
+	 * Ignore entries that didn't accumulate any actual counts.
 	 */
 	if (memcmp(&lstats->t_counts, &all_zeroes,
 			   sizeof(PgStat_TableCounts)) == 0)
@@ -783,6 +759,7 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 	if (lstats->t_counts.t_numscans)
 	{
 		TimestampTz t = GetCurrentTransactionStopTimestamp();
+
 		if (t > tabentry->lastscan)
 			tabentry->lastscan = t;
 	}
@@ -831,12 +808,12 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 }
 
 void
-pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref)
+pgstat_table_delete_pending_cb(PgStat_EntryRef *entry_ref)
 {
 	PgStat_TableStatus *pending = (PgStat_TableStatus *) entry_ref->pending;
 
 	if (pending->relation)
-		pgstat_unlink_relation(pending->relation);
+		pgstat_unlink_table(pending->relation);
 }
 
 /*
@@ -844,12 +821,12 @@ pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref)
  * initialized if not exists.
  */
 static PgStat_TableStatus *
-pgstat_prep_relation_pending(Oid rel_id, bool isshared)
+pgstat_prep_table_pending(Oid rel_id, bool isshared)
 {
 	PgStat_EntryRef *entry_ref;
 	PgStat_TableStatus *pending;
 
-	entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_RELATION,
+	entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_TABLE,
 										  isshared ? InvalidOid : MyDatabaseId,
 										  rel_id, NULL);
 	pending = entry_ref->pending;
@@ -863,7 +840,7 @@ pgstat_prep_relation_pending(Oid rel_id, bool isshared)
  * add a new (sub)transaction state record
  */
 static void
-add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
+add_tabstat_xact_level(PgStat_TableStatus *pgstattab_info, int nest_level)
 {
 	PgStat_SubXactStatus *xact_state;
 	PgStat_TableXactStatus *trans;
@@ -879,24 +856,24 @@ add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
 		MemoryContextAllocZero(TopTransactionContext,
 							   sizeof(PgStat_TableXactStatus));
 	trans->nest_level = nest_level;
-	trans->upper = pgstat_info->trans;
-	trans->parent = pgstat_info;
+	trans->upper = pgstattab_info->trans;
+	trans->parent = pgstattab_info;
 	trans->next = xact_state->first;
 	xact_state->first = trans;
-	pgstat_info->trans = trans;
+	pgstattab_info->trans = trans;
 }
 
 /*
  * Add a new (sub)transaction record if needed.
  */
 static void
-ensure_tabstat_xact_level(PgStat_TableStatus *pgstat_info)
+ensure_tabstat_xact_level(PgStat_TableStatus *pgstattab_info)
 {
 	int			nest_level = GetCurrentTransactionNestLevel();
 
-	if (pgstat_info->trans == NULL ||
-		pgstat_info->trans->nest_level != nest_level)
-		add_tabstat_xact_level(pgstat_info, nest_level);
+	if (pgstattab_info->trans == NULL ||
+		pgstattab_info->trans->nest_level != nest_level)
+		add_tabstat_xact_level(pgstattab_info, nest_level);
 }
 
 /*
diff --git a/src/backend/utils/activity/pgstat_xact.c b/src/backend/utils/activity/pgstat_xact.c
index 5a3aca4aef..870f1b1103 100644
--- a/src/backend/utils/activity/pgstat_xact.c
+++ b/src/backend/utils/activity/pgstat_xact.c
@@ -51,7 +51,7 @@ AtEOXact_PgStat(bool isCommit, bool parallel)
 		Assert(xact_state->nest_level == 1);
 		Assert(xact_state->prev == NULL);
 
-		AtEOXact_PgStat_Relations(xact_state, isCommit);
+		AtEOXact_PgStat_Tables(xact_state, isCommit);
 		AtEOXact_PgStat_DroppedStats(xact_state, isCommit);
 	}
 	pgStatXactStack = NULL;
@@ -122,7 +122,7 @@ AtEOSubXact_PgStat(bool isCommit, int nestDepth)
 		/* delink xact_state from stack immediately to simplify reuse case */
 		pgStatXactStack = xact_state->prev;
 
-		AtEOSubXact_PgStat_Relations(xact_state, isCommit, nestDepth);
+		AtEOSubXact_PgStat_Tables(xact_state, isCommit, nestDepth);
 		AtEOSubXact_PgStat_DroppedStats(xact_state, isCommit, nestDepth);
 
 		pfree(xact_state);
@@ -197,7 +197,7 @@ AtPrepare_PgStat(void)
 		Assert(xact_state->nest_level == 1);
 		Assert(xact_state->prev == NULL);
 
-		AtPrepare_PgStat_Relations(xact_state);
+		AtPrepare_PgStat_Tables(xact_state);
 	}
 }
 
@@ -221,7 +221,7 @@ PostPrepare_PgStat(void)
 		Assert(xact_state->nest_level == 1);
 		Assert(xact_state->prev == NULL);
 
-		PostPrepare_PgStat_Relations(xact_state);
+		PostPrepare_PgStat_Tables(xact_state);
 	}
 	pgStatXactStack = NULL;
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 973979508d..dea762c116 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -36,106 +36,124 @@
 
 #define HAS_PGSTAT_PERMISSIONS(role)	 (has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role))
 
-#define PG_STAT_GET_RELENTRY_INT64(stat)						\
-Datum															\
-CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
-{																\
-	Oid			relid = PG_GETARG_OID(0);						\
-	int64		result;											\
-	PgStat_StatTabEntry *tabentry;								\
-																\
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)	\
-		result = 0;												\
-	else														\
-		result = (int64) (tabentry->stat);						\
-																\
-	PG_RETURN_INT64(result);									\
-}																\
+#define PG_STAT_GET_RELENTRY_INT64(Relkind,relkind,stat)				\
+Datum																	\
+pg_stat_get_##relkind##_##stat(PG_FUNCTION_ARGS)						\
+{																		\
+	Oid			relid = PG_GETARG_OID(0);								\
+	int64		result;													\
+	PgStat_Stat##Relkind##Entry *entry;									\
+																		\
+	if ((entry = pgstat_fetch_stat_##relkind##entry(relid)) == NULL)	\
+		result = 0;														\
+	else																\
+		result = (int64) (entry->stat);									\
+																		\
+	PG_RETURN_INT64(result);											\
+}
+
+/* pg_stat_get_tab_analyze_count */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,analyze_count);
+
+/* pg_stat_get_tab_autoanalyze_count */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,autoanalyze_count);
+
+/* pg_stat_get_tab_autovacuum_count */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,autovacuum_count);
+
+/* pg_stat_get_tab_blocks_fetched */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,blocks_fetched);
+
+/* pg_stat_get_tab_blocks_hit */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,blocks_hit);
+
+/* pg_stat_get_tab_dead_tuples */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,dead_tuples);
 
-/* pg_stat_get_analyze_count */
-PG_STAT_GET_RELENTRY_INT64(analyze_count);
+/* pg_stat_get_tab_ins_since_vacuum */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,ins_since_vacuum);
 
-/* pg_stat_get_autoanalyze_count */
-PG_STAT_GET_RELENTRY_INT64(autoanalyze_count);
+/* pg_stat_get_tab_live_tuples */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,live_tuples);
 
-/* pg_stat_get_autovacuum_count */
-PG_STAT_GET_RELENTRY_INT64(autovacuum_count);
+/* pg_stat_get_mod_since_analyze */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,mod_since_analyze);
 
-/* pg_stat_get_blocks_fetched */
-PG_STAT_GET_RELENTRY_INT64(blocks_fetched);
+/* pg_stat_get_tab_numscans */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,numscans);
 
-/* pg_stat_get_blocks_hit */
-PG_STAT_GET_RELENTRY_INT64(blocks_hit);
+/* pg_stat_get_tab_tuples_deleted */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_deleted);
 
-/* pg_stat_get_dead_tuples */
-PG_STAT_GET_RELENTRY_INT64(dead_tuples);
+/* pg_stat_get_tab_tuples_fetched */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_fetched);
 
-/* pg_stat_get_ins_since_vacuum */
-PG_STAT_GET_RELENTRY_INT64(ins_since_vacuum);
+/* pg_stat_get_tab_tuples_hot_updated */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_hot_updated);
 
-/* pg_stat_get_live_tuples */
-PG_STAT_GET_RELENTRY_INT64(live_tuples);
+/* pg_stat_get_tab_tuples_inserted */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_inserted);
 
-/* pg_stat_get_mods_since_analyze */
-PG_STAT_GET_RELENTRY_INT64(mod_since_analyze);
+/* pg_stat_get_tab_tuples_returned */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_returned);
 
-/* pg_stat_get_numscans */
-PG_STAT_GET_RELENTRY_INT64(numscans);
+/* pg_stat_get_tab_tuples_updated */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_updated);
 
-/* pg_stat_get_tuples_deleted */
-PG_STAT_GET_RELENTRY_INT64(tuples_deleted);
+/* pg_stat_get_tab_vacuum_count */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,vacuum_count);
 
-/* pg_stat_get_tuples_fetched */
-PG_STAT_GET_RELENTRY_INT64(tuples_fetched);
+/* pg_stat_get_ind_numscans */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,numscans);
 
-/* pg_stat_get_tuples_hot_updated */
-PG_STAT_GET_RELENTRY_INT64(tuples_hot_updated);
+/* pg_stat_get_ind_tuples_returned */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,tuples_returned);
 
-/* pg_stat_get_tuples_inserted */
-PG_STAT_GET_RELENTRY_INT64(tuples_inserted);
+/* pg_stat_get_ind_tuples_fetched */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,tuples_fetched);
 
-/* pg_stat_get_tuples_returned */
-PG_STAT_GET_RELENTRY_INT64(tuples_returned);
+/* pg_stat_get_ind_blocks_fetched */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,blocks_fetched);
 
-/* pg_stat_get_tuples_updated */
-PG_STAT_GET_RELENTRY_INT64(tuples_updated);
+/* pg_stat_get_ind_blocks_hit */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,blocks_hit);
 
-/* pg_stat_get_vacuum_count */
-PG_STAT_GET_RELENTRY_INT64(vacuum_count);
+#define PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Relkind,relkind,stat)			\
+Datum																	\
+pg_stat_get_##relkind##_##stat(PG_FUNCTION_ARGS)						\
+{																		\
+	Oid			relid = PG_GETARG_OID(0);								\
+	TimestampTz		result;												\
+	PgStat_Stat##Relkind##Entry *entry;									\
+																		\
+	if ((entry = pgstat_fetch_stat_##relkind##entry(relid)) == NULL)	\
+		result = 0;														\
+	else																\
+		result = entry->stat;											\
+																		\
+	if (result == 0)													\
+		PG_RETURN_NULL();												\
+	else																\
+		PG_RETURN_TIMESTAMPTZ(result);									\
+}
 
-#define PG_STAT_GET_RELENTRY_TIMESTAMPTZ(stat)					\
-Datum															\
-CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
-{																\
-	Oid			relid = PG_GETARG_OID(0);						\
-	TimestampTz result;											\
-	PgStat_StatTabEntry *tabentry;								\
-																\
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)	\
-		result = 0;												\
-	else														\
-		result = tabentry->stat;								\
-																\
-	if (result == 0)											\
-		PG_RETURN_NULL();										\
-	else														\
-		PG_RETURN_TIMESTAMPTZ(result);							\
-}																\
+/* pg_stat_get_tab_last_analyze_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,last_analyze_time);
 
-/* pg_stat_get_last_analyze_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_analyze_time);
+/* pg_stat_get_tab_last_autoanalyze_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,last_autoanalyze_time);
 
-/* pg_stat_get_last_autoanalyze_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autoanalyze_time);
+/* pg_stat_get_tab_last_autovacuum_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,last_autovacuum_time);
 
-/* pg_stat_get_last_autovacuum_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autovacuum_time);
+/* pg_stat_get_tab_last_vacuum_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,last_vacuum_time);
 
-/* pg_stat_get_last_vacuum_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_vacuum_time);
+/* pg_stat_get_tab_lastscan */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,lastscan);
 
-/* pg_stat_get_lastscan */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(lastscan);
+/* pg_stat_get_ind_lastscan */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Ind,ind,lastscan);
 
 Datum
 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
@@ -1586,7 +1604,7 @@ pg_stat_get_slru(PG_FUNCTION_ARGS)
 }
 
 Datum
-pg_stat_get_xact_numscans(PG_FUNCTION_ARGS)
+pg_stat_get_tab_xact_numscans(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
@@ -1600,17 +1618,32 @@ pg_stat_get_xact_numscans(PG_FUNCTION_ARGS)
 	PG_RETURN_INT64(result);
 }
 
+Datum
+pg_stat_get_ind_xact_numscans(PG_FUNCTION_ARGS)
+{
+	Oid			relid = PG_GETARG_OID(0);
+	int64		result;
+	PgStat_IndexStatus *indentry;
+
+	if ((indentry = find_indstat_entry(relid)) == NULL)
+		result = 0;
+	else
+		result = (int64) (indentry->i_counts.i_numscans);
+
+	PG_RETURN_INT64(result);
+}
+
 Datum
 pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
-	PgStat_TableStatus *tabentry;
+	PgStat_IndexStatus *indentry;
 
-	if ((tabentry = find_tabstat_entry(relid)) == NULL)
+	if ((indentry = find_indstat_entry(relid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (tabentry->t_counts.t_tuples_returned);
+		result = (int64) (indentry->i_counts.i_tuples_returned);
 
 	PG_RETURN_INT64(result);
 }
@@ -1620,12 +1653,12 @@ pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
-	PgStat_TableStatus *tabentry;
+	PgStat_IndexStatus *indentry;
 
-	if ((tabentry = find_tabstat_entry(relid)) == NULL)
+	if ((indentry = find_indstat_entry(relid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (tabentry->t_counts.t_tuples_fetched);
+		result = (int64) (indentry->i_counts.i_tuples_fetched);
 
 	PG_RETURN_INT64(result);
 }
@@ -1713,12 +1746,12 @@ pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
-	PgStat_TableStatus *tabentry;
+	PgStat_IndexStatus *indentry;
 
-	if ((tabentry = find_tabstat_entry(relid)) == NULL)
+	if ((indentry = find_indstat_entry(relid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (tabentry->t_counts.t_blocks_fetched);
+		result = (int64) (indentry->i_counts.i_blocks_fetched);
 
 	PG_RETURN_INT64(result);
 }
@@ -1728,12 +1761,12 @@ pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
-	PgStat_TableStatus *tabentry;
+	PgStat_IndexStatus *indentry;
 
-	if ((tabentry = find_tabstat_entry(relid)) == NULL)
+	if ((indentry = find_indstat_entry(relid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (tabentry->t_counts.t_blocks_hit);
+		result = (int64) (indentry->i_counts.i_blocks_hit);
 
 	PG_RETURN_INT64(result);
 }
@@ -1852,7 +1885,8 @@ pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
 {
 	Oid			taboid = PG_GETARG_OID(0);
 
-	pgstat_reset(PGSTAT_KIND_RELATION, MyDatabaseId, taboid);
+	pgstat_reset(PGSTAT_KIND_TABLE, MyDatabaseId, taboid);
+	pgstat_reset(PGSTAT_KIND_INDEX, MyDatabaseId, taboid);
 
 	PG_RETURN_VOID();
 }
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index a50eecc7c8..e74704742c 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -2411,7 +2411,10 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc)
 	RelationCloseSmgr(relation);
 
 	/* break mutual link with stats entry */
-	pgstat_unlink_relation(relation);
+	if (relation->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_unlink_index(relation);
+	else
+		pgstat_unlink_table(relation);
 
 	/*
 	 * Free all the subsidiary data structures of the relcache entry, then the
@@ -2727,8 +2730,9 @@ RelationClearRelation(Relation relation, bool rebuild)
 			SWAPFIELD(RowSecurityDesc *, rd_rsdesc);
 		/* toast OID override must be preserved */
 		SWAPFIELD(Oid, rd_toastoid);
-		/* pgstat_info / enabled must be preserved */
-		SWAPFIELD(struct PgStat_TableStatus *, pgstat_info);
+		/* pgstattab_info / pgstatind_info / enabled must be preserved */
+		SWAPFIELD(struct PgStat_TableStatus *, pgstattab_info);
+		SWAPFIELD(struct PgStat_IndexStatus *, pgstatind_info);
 		SWAPFIELD(bool, pgstat_enabled);
 		/* preserve old partition key if we have one */
 		if (keep_partkey)
@@ -6321,7 +6325,8 @@ load_relcache_init_file(bool shared)
 		rel->rd_firstRelfilelocatorSubid = InvalidSubTransactionId;
 		rel->rd_droppedSubid = InvalidSubTransactionId;
 		rel->rd_amcache = NULL;
-		rel->pgstat_info = NULL;
+		rel->pgstattab_info = NULL;
+		rel->pgstatind_info = NULL;
 
 		/*
 		 * Recompute lock and physical addressing info.  This is needed in
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f9301b2627..c3fe4af669 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5274,96 +5274,120 @@
   proargnames => '{mcv_list,index,values,nulls,frequency,base_frequency}',
   prosrc => 'pg_stats_ext_mcvlist_items' },
 
-{ oid => '1928', descr => 'statistics: number of scans done for table/index',
-  proname => 'pg_stat_get_numscans', provolatile => 's', proparallel => 'r',
+{ oid => '1928', descr => 'statistics: number of scans done for table',
+  proname => 'pg_stat_get_tab_numscans', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_numscans' },
-{ oid => '9976', descr => 'statistics: time of the last scan for table/index',
-  proname => 'pg_stat_get_lastscan', provolatile => 's', proparallel => 'r',
+  prosrc => 'pg_stat_get_tab_numscans' },
+{ oid => '8296', descr => 'statistics: number of scans done for index',
+  proname => 'pg_stat_get_ind_numscans', provolatile => 's', proparallel => 'r',
+  prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_ind_numscans' },
+{ oid => '9976', descr => 'statistics: time of the last scan for table',
+  proname => 'pg_stat_get_tab_lastscan', provolatile => 's', proparallel => 'r',
+  prorettype => 'timestamptz', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_tab_lastscan' },
+{ oid => '8626', descr => 'statistics: time of the last scan for index',
+  proname => 'pg_stat_get_ind_lastscan', provolatile => 's', proparallel => 'r',
   prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_lastscan' },
+  prosrc => 'pg_stat_get_ind_lastscan' },
 { oid => '1929', descr => 'statistics: number of tuples read by seqscan',
-  proname => 'pg_stat_get_tuples_returned', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_returned', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_returned' },
+  prosrc => 'pg_stat_get_tab_tuples_returned' },
+{ oid => '9603', descr => 'statistics: number of tuples read by seqscan',
+  proname => 'pg_stat_get_ind_tuples_returned', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_ind_tuples_returned' },
 { oid => '1930', descr => 'statistics: number of tuples fetched by idxscan',
-  proname => 'pg_stat_get_tuples_fetched', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_fetched', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_tab_tuples_fetched' },
+{ oid => '8526', descr => 'statistics: number of tuples fetched by idxscan',
+  proname => 'pg_stat_get_ind_tuples_fetched', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_fetched' },
+  prosrc => 'pg_stat_get_ind_tuples_fetched' },
 { oid => '1931', descr => 'statistics: number of tuples inserted',
-  proname => 'pg_stat_get_tuples_inserted', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_inserted', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_inserted' },
+  prosrc => 'pg_stat_get_tab_tuples_inserted' },
 { oid => '1932', descr => 'statistics: number of tuples updated',
-  proname => 'pg_stat_get_tuples_updated', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_updated', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_updated' },
+  prosrc => 'pg_stat_get_tab_tuples_updated' },
 { oid => '1933', descr => 'statistics: number of tuples deleted',
-  proname => 'pg_stat_get_tuples_deleted', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_deleted', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_deleted' },
+  prosrc => 'pg_stat_get_tab_tuples_deleted' },
 { oid => '1972', descr => 'statistics: number of tuples hot updated',
-  proname => 'pg_stat_get_tuples_hot_updated', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_hot_updated', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_hot_updated' },
+  prosrc => 'pg_stat_get_tab_tuples_hot_updated' },
 { oid => '2878', descr => 'statistics: number of live tuples',
-  proname => 'pg_stat_get_live_tuples', provolatile => 's', proparallel => 'r',
+  proname => 'pg_stat_get_tab_live_tuples', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_live_tuples' },
+  prosrc => 'pg_stat_get_tab_live_tuples' },
 { oid => '2879', descr => 'statistics: number of dead tuples',
-  proname => 'pg_stat_get_dead_tuples', provolatile => 's', proparallel => 'r',
+  proname => 'pg_stat_get_tab_dead_tuples', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_dead_tuples' },
+  prosrc => 'pg_stat_get_tab_dead_tuples' },
 { oid => '3177',
   descr => 'statistics: number of tuples changed since last analyze',
-  proname => 'pg_stat_get_mod_since_analyze', provolatile => 's',
+  proname => 'pg_stat_get_tab_mod_since_analyze', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_mod_since_analyze' },
+  prosrc => 'pg_stat_get_tab_mod_since_analyze' },
 { oid => '5053',
   descr => 'statistics: number of tuples inserted since last vacuum',
-  proname => 'pg_stat_get_ins_since_vacuum', provolatile => 's',
+  proname => 'pg_stat_get_tab_ins_since_vacuum', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_ins_since_vacuum' },
+  prosrc => 'pg_stat_get_tab_ins_since_vacuum' },
 { oid => '1934', descr => 'statistics: number of blocks fetched',
-  proname => 'pg_stat_get_blocks_fetched', provolatile => 's',
+  proname => 'pg_stat_get_tab_blocks_fetched', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_blocks_fetched' },
+  prosrc => 'pg_stat_get_tab_blocks_fetched' },
+{ oid => '9432', descr => 'statistics: number of blocks fetched',
+  proname => 'pg_stat_get_ind_blocks_fetched', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_ind_blocks_fetched' },
 { oid => '1935', descr => 'statistics: number of blocks found in cache',
-  proname => 'pg_stat_get_blocks_hit', provolatile => 's', proparallel => 'r',
+  proname => 'pg_stat_get_tab_blocks_hit', provolatile => 's', proparallel => 'r',
+  prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_tab_blocks_hit' },
+{ oid => '8354', descr => 'statistics: number of blocks found in cache',
+  proname => 'pg_stat_get_ind_blocks_hit', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_blocks_hit' },
+  prosrc => 'pg_stat_get_ind_blocks_hit' },
 { oid => '2781', descr => 'statistics: last manual vacuum time for a table',
-  proname => 'pg_stat_get_last_vacuum_time', provolatile => 's',
+  proname => 'pg_stat_get_tab_last_vacuum_time', provolatile => 's',
   proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_last_vacuum_time' },
+  prosrc => 'pg_stat_get_tab_last_vacuum_time' },
 { oid => '2782', descr => 'statistics: last auto vacuum time for a table',
-  proname => 'pg_stat_get_last_autovacuum_time', provolatile => 's',
+  proname => 'pg_stat_get_tab_last_autovacuum_time', provolatile => 's',
   proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_last_autovacuum_time' },
+  prosrc => 'pg_stat_get_tab_last_autovacuum_time' },
 { oid => '2783', descr => 'statistics: last manual analyze time for a table',
-  proname => 'pg_stat_get_last_analyze_time', provolatile => 's',
+  proname => 'pg_stat_get_tab_last_analyze_time', provolatile => 's',
   proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_last_analyze_time' },
+  prosrc => 'pg_stat_get_tab_last_analyze_time' },
 { oid => '2784', descr => 'statistics: last auto analyze time for a table',
-  proname => 'pg_stat_get_last_autoanalyze_time', provolatile => 's',
+  proname => 'pg_stat_get_tab_last_autoanalyze_time', provolatile => 's',
   proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_last_autoanalyze_time' },
+  prosrc => 'pg_stat_get_tab_last_autoanalyze_time' },
 { oid => '3054', descr => 'statistics: number of manual vacuums for a table',
-  proname => 'pg_stat_get_vacuum_count', provolatile => 's', proparallel => 'r',
+  proname => 'pg_stat_get_tab_vacuum_count', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_vacuum_count' },
+  prosrc => 'pg_stat_get_tab_vacuum_count' },
 { oid => '3055', descr => 'statistics: number of auto vacuums for a table',
-  proname => 'pg_stat_get_autovacuum_count', provolatile => 's',
+  proname => 'pg_stat_get_tab_autovacuum_count', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_autovacuum_count' },
+  prosrc => 'pg_stat_get_tab_autovacuum_count' },
 { oid => '3056', descr => 'statistics: number of manual analyzes for a table',
-  proname => 'pg_stat_get_analyze_count', provolatile => 's',
+  proname => 'pg_stat_get_tab_analyze_count', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_analyze_count' },
+  prosrc => 'pg_stat_get_tab_analyze_count' },
 { oid => '3057', descr => 'statistics: number of auto analyzes for a table',
-  proname => 'pg_stat_get_autoanalyze_count', provolatile => 's',
+  proname => 'pg_stat_get_tab_autoanalyze_count', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_autoanalyze_count' },
+  prosrc => 'pg_stat_get_tab_autoanalyze_count' },
 { oid => '1936', descr => 'statistics: currently active backend IDs',
   proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
   provolatile => 's', proparallel => 'r', prorettype => 'int4',
@@ -5719,10 +5743,15 @@
   prosrc => 'pg_stat_get_function_self_time' },
 
 { oid => '3037',
-  descr => 'statistics: number of scans done for table/index in current transaction',
-  proname => 'pg_stat_get_xact_numscans', provolatile => 'v',
+  descr => 'statistics: number of scans done for table in current transaction',
+  proname => 'pg_stat_get_tab_xact_numscans', provolatile => 'v',
+  proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_tab_xact_numscans' },
+{ oid => '8892',
+  descr => 'statistics: number of scans done for index in current transaction',
+  proname => 'pg_stat_get_ind_xact_numscans', provolatile => 'v',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_xact_numscans' },
+  prosrc => 'pg_stat_get_ind_xact_numscans' },
 { oid => '3038',
   descr => 'statistics: number of tuples read by seqscan in current transaction',
   proname => 'pg_stat_get_xact_tuples_returned', provolatile => 'v',
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index bc6349727b..57f5c8657a 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -39,7 +39,8 @@ typedef enum PgStat_Kind
 
 	/* stats for variable-numbered objects */
 	PGSTAT_KIND_DATABASE,		/* database-wide statistics */
-	PGSTAT_KIND_RELATION,		/* per-table statistics */
+	PGSTAT_KIND_TABLE,			/* per-table statistics */
+	PGSTAT_KIND_INDEX,			/* per-index statistics */
 	PGSTAT_KIND_FUNCTION,		/* per-function statistics */
 	PGSTAT_KIND_REPLSLOT,		/* per-slot statistics */
 	PGSTAT_KIND_SUBSCRIPTION,	/* per-subscription statistics */
@@ -145,6 +146,28 @@ typedef struct PgStat_BackendSubEntry
 	PgStat_Counter sync_error_count;
 } PgStat_BackendSubEntry;
 
+/* ----------
+ * PgStat_IndexCounts			The actual per-index counts kept by a backend
+ *
+ * This struct should contain only actual event counters, because we memcmp
+ * it against zeroes to detect whether there are any stats updates to apply.
+ * It is a component of PgStat_IndexStatus (within-backend state).
+ *
+ * tuples_returned is the number of index entries returned by
+ * the index AM, while tuples_fetched is the number of tuples successfully
+ * fetched by heap_fetch under the control of simple indexscans for this index.
+ * ----------
+ */
+typedef struct PgStat_IndexCounts
+{
+	PgStat_Counter i_numscans;
+
+	PgStat_Counter i_tuples_returned;
+	PgStat_Counter i_tuples_fetched;
+	PgStat_Counter i_blocks_fetched;
+	PgStat_Counter i_blocks_hit;
+} PgStat_IndexCounts;
+
 /* ----------
  * PgStat_TableCounts			The actual per-table counts kept by a backend
  *
@@ -152,12 +175,9 @@ typedef struct PgStat_BackendSubEntry
  * it against zeroes to detect whether there are any stats updates to apply.
  * It is a component of PgStat_TableStatus (within-backend state).
  *
- * Note: for a table, tuples_returned is the number of tuples successfully
+ * Note: tuples_returned is the number of tuples successfully
  * fetched by heap_getnext, while tuples_fetched is the number of tuples
  * successfully fetched by heap_fetch under the control of bitmap indexscans.
- * For an index, tuples_returned is the number of index entries returned by
- * the index AM, while tuples_fetched is the number of tuples successfully
- * fetched by heap_fetch under the control of simple indexscans for this index.
  *
  * tuples_inserted/updated/deleted/hot_updated count attempted actions,
  * regardless of whether the transaction committed.  delta_live_tuples,
@@ -210,6 +230,22 @@ typedef struct PgStat_TableStatus
 	Relation	relation;		/* rel that is using this entry */
 } PgStat_TableStatus;
 
+/* ----------
+ * PgStat_IndexStatus			Per-index status within a backend
+ *
+ * Many of the event counters are nontransactional, ie, we count events
+ * in committed and aborted transactions alike.  For these, we just count
+ * directly in the PgStat_IndexStatus.
+ * ----------
+ */
+typedef struct PgStat_IndexStatus
+{
+	Oid			r_id;			/* relation's OID */
+	bool		r_shared;		/* is it a shared catalog? */
+	PgStat_IndexCounts i_counts;	/* event counts to be sent */
+	Relation	relation;		/* rel that is using this entry */
+} PgStat_IndexStatus;
+
 /* ----------
  * PgStat_TableXactStatus		Per-table, per-subtransaction status
  * ----------
@@ -382,6 +418,17 @@ typedef struct PgStat_StatTabEntry
 	PgStat_Counter autoanalyze_count;
 } PgStat_StatTabEntry;
 
+typedef struct PgStat_StatIndEntry
+{
+	PgStat_Counter numscans;
+	TimestampTz lastscan;
+
+	PgStat_Counter tuples_returned;
+	PgStat_Counter tuples_fetched;
+	PgStat_Counter blocks_fetched;
+	PgStat_Counter blocks_hit;
+} PgStat_StatIndEntry;
+
 typedef struct PgStat_WalStats
 {
 	PgStat_Counter wal_records;
@@ -494,16 +541,15 @@ extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
 
 
 /*
- * Functions in pgstat_relation.c
+ * Functions in pgstat_table.c
  */
 
-extern void pgstat_create_relation(Relation rel);
-extern void pgstat_drop_relation(Relation rel);
-extern void pgstat_copy_relation_stats(Relation dst, Relation src);
+extern void pgstat_create_table(Relation rel);
+extern void pgstat_drop_table(Relation rel);
+extern void pgstat_init_table(Relation rel);
 
-extern void pgstat_init_relation(Relation rel);
-extern void pgstat_assoc_relation(Relation rel);
-extern void pgstat_unlink_relation(Relation rel);
+extern void pgstat_assoc_table(Relation rel);
+extern void pgstat_unlink_table(Relation rel);
 
 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
 								 PgStat_Counter livetuples, PgStat_Counter deadtuples);
@@ -511,53 +557,83 @@ extern void pgstat_report_analyze(Relation rel,
 								  PgStat_Counter livetuples, PgStat_Counter deadtuples,
 								  bool resetcounter);
 
+/*
+ * Functions in pgstat_index.c
+ */
+
+extern void pgstat_create_index(Relation rel);
+extern void pgstat_drop_index(Relation rel);
+extern void pgstat_copy_index_stats(Relation dst, Relation src);
+extern void pgstat_init_index(Relation rel);
+extern void pgstat_assoc_index(Relation rel);
+extern void pgstat_unlink_index(Relation rel);
+
 /*
  * If stats are enabled, but pending data hasn't been prepared yet, call
- * pgstat_assoc_relation() to do so. See its comment for why this is done
- * separately from pgstat_init_relation().
+ * pgstat_assoc_table() / pgstat_assoc_index() to do so.
+ * See their comment for why this is done separately from pgstat_init_table()
+ * and pgstat_init_index().
  */
-#define pgstat_should_count_relation(rel)                           \
-	(likely((rel)->pgstat_info != NULL) ? true :                    \
-	 ((rel)->pgstat_enabled ? pgstat_assoc_relation(rel), true : false))
+#define pgstat_should_count_table(rel)                           \
+	(likely((rel)->pgstattab_info != NULL) ? true :                    \
+	 ((rel)->pgstat_enabled ? pgstat_assoc_table(rel), true : false))
+
+#define pgstat_should_count_index(rel)                           \
+	(likely((rel)->pgstatind_info != NULL) ? true :                    \
+	 ((rel)->pgstat_enabled ? pgstat_assoc_index(rel), true : false))
 
 /* nontransactional event counts are simple enough to inline */
 
 #define pgstat_count_heap_scan(rel)									\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_numscans++;				\
+		if (pgstat_should_count_table(rel))						\
+			(rel)->pgstattab_info->t_counts.t_numscans++;				\
 	} while (0)
 #define pgstat_count_heap_getnext(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_tuples_returned++;		\
+		if (pgstat_should_count_table(rel))						\
+			(rel)->pgstattab_info->t_counts.t_tuples_returned++;		\
 	} while (0)
 #define pgstat_count_heap_fetch(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_tuples_fetched++;		\
+		if (pgstat_should_count_table(rel))						\
+			(rel)->pgstattab_info->t_counts.t_tuples_fetched++;		\
+	} while (0)
+#define pgstat_count_index_fetch(rel)								\
+	do {															\
+		if (pgstat_should_count_index(rel))						\
+			(rel)->pgstatind_info->i_counts.i_tuples_fetched++;		\
 	} while (0)
 #define pgstat_count_index_scan(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_numscans++;				\
+		if (pgstat_should_count_index(rel))						\
+			(rel)->pgstatind_info->i_counts.i_numscans++;			\
 	} while (0)
 #define pgstat_count_index_tuples(rel, n)							\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_tuples_returned += (n);	\
+		if (pgstat_should_count_index(rel))						\
+			(rel)->pgstatind_info->i_counts.i_tuples_returned += (n);	\
 	} while (0)
-#define pgstat_count_buffer_read(rel)								\
+#define pgstat_count_table_buffer_read(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_blocks_fetched++;		\
+		if (pgstat_should_count_table(rel))	\
+			(rel)->pgstattab_info->t_counts.t_blocks_fetched++;		\
 	} while (0)
-#define pgstat_count_buffer_hit(rel)								\
+#define pgstat_count_index_buffer_read(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_blocks_hit++;			\
+		if (pgstat_should_count_index(rel))	\
+			(rel)->pgstatind_info->i_counts.i_blocks_fetched++;		\
+	} while (0)
+#define pgstat_count_table_buffer_hit(rel)								\
+	do {															\
+		if (pgstat_should_count_table(rel))	\
+			(rel)->pgstattab_info->t_counts.t_blocks_hit++; \
+	} while (0)
+#define pgstat_count_index_buffer_hit(rel)								\
+	do {															\
+		if (pgstat_should_count_index(rel))	\
+			(rel)->pgstatind_info->i_counts.i_blocks_hit++; \
 	} while (0)
-
 extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n);
 extern void pgstat_count_heap_update(Relation rel, bool hot);
 extern void pgstat_count_heap_delete(Relation rel);
@@ -573,6 +649,10 @@ extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry_ext(bool shared,
 														   Oid reloid);
 extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
+extern PgStat_IndexStatus *find_indstat_entry(Oid rel_id);
+extern PgStat_StatIndEntry *pgstat_fetch_stat_indentry(Oid relid);
+extern PgStat_StatIndEntry *pgstat_fetch_stat_indentry_ext(bool shared,
+														   Oid relid);
 
 
 /*
diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
index e2c7b59324..004e5412ab 100644
--- a/src/include/utils/pgstat_internal.h
+++ b/src/include/utils/pgstat_internal.h
@@ -359,11 +359,17 @@ typedef struct PgStatShared_Database
 	PgStat_StatDBEntry stats;
 } PgStatShared_Database;
 
-typedef struct PgStatShared_Relation
+typedef struct PgStatShared_Table
 {
 	PgStatShared_Common header;
 	PgStat_StatTabEntry stats;
-} PgStatShared_Relation;
+} PgStatShared_Table;
+
+typedef struct PgStatShared_Index
+{
+	PgStatShared_Common header;
+	PgStat_StatIndEntry stats;
+} PgStatShared_Index;
 
 typedef struct PgStatShared_Function
 {
@@ -550,16 +556,23 @@ extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
 
 
 /*
- * Functions in pgstat_relation.c
+ * Functions in pgstat_table.c
  */
 
-extern void AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit);
-extern void AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth);
-extern void AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
-extern void PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
+extern void AtEOXact_PgStat_Tables(PgStat_SubXactStatus *xact_state, bool isCommit);
+extern void AtEOSubXact_PgStat_Tables(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth);
+extern void AtPrepare_PgStat_Tables(PgStat_SubXactStatus *xact_state);
+extern void PostPrepare_PgStat_Tables(PgStat_SubXactStatus *xact_state);
+
+extern bool pgstat_table_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+extern void pgstat_table_delete_pending_cb(PgStat_EntryRef *entry_ref);
+
+/*
+ * Functions in pgstat_index.c
+ */
 
-extern bool pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
-extern void pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref);
+extern bool pgstat_index_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+extern void pgstat_index_delete_pending_cb(PgStat_EntryRef *entry_ref);
 
 
 /*
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index f383a2fca9..796423f3e3 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -248,7 +248,10 @@ typedef struct RelationData
 
 	bool		pgstat_enabled; /* should relation stats be counted */
 	/* use "struct" here to avoid needing to include pgstat.h: */
-	struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
+	/* table's statistics collection area */
+	struct PgStat_TableStatus *pgstattab_info;
+	/* Index's statistics collection area */
+	struct PgStat_IndexStatus *pgstatind_info;
 } RelationData;
 
 
diff --git a/src/test/isolation/expected/stats.out b/src/test/isolation/expected/stats.out
index 61b5a710ec..494adee88b 100644
--- a/src/test/isolation/expected/stats.out
+++ b/src/test/isolation/expected/stats.out
@@ -2166,14 +2166,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2210,14 +2210,14 @@ step s2_table_update_k1: UPDATE test_stat_tab SET value = value + 1 WHERE key =
 step s1_table_drop: DROP TABLE test_stat_tab;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2236,14 +2236,14 @@ pg_stat_force_next_flush
 step s1_track_counts_off: SET track_counts = off;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2275,14 +2275,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2314,14 +2314,14 @@ pg_stat_force_next_flush
 step s1_track_counts_off: SET track_counts = off;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2369,14 +2369,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2401,14 +2401,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2463,14 +2463,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2495,14 +2495,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2558,14 +2558,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2627,14 +2627,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2688,14 +2688,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2755,14 +2755,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2795,14 +2795,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2841,14 +2841,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2881,14 +2881,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2927,14 +2927,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2968,14 +2968,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -3015,14 +3015,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
diff --git a/src/test/isolation/expected/stats_1.out b/src/test/isolation/expected/stats_1.out
index 3854320106..7981747732 100644
--- a/src/test/isolation/expected/stats_1.out
+++ b/src/test/isolation/expected/stats_1.out
@@ -2174,14 +2174,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2218,14 +2218,14 @@ step s2_table_update_k1: UPDATE test_stat_tab SET value = value + 1 WHERE key =
 step s1_table_drop: DROP TABLE test_stat_tab;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2244,14 +2244,14 @@ pg_stat_force_next_flush
 step s1_track_counts_off: SET track_counts = off;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2283,14 +2283,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2322,14 +2322,14 @@ pg_stat_force_next_flush
 step s1_track_counts_off: SET track_counts = off;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2377,14 +2377,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2409,14 +2409,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2471,14 +2471,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2503,14 +2503,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2566,14 +2566,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2635,14 +2635,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2698,14 +2698,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2767,14 +2767,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2809,14 +2809,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2857,14 +2857,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2899,14 +2899,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2947,14 +2947,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2990,14 +2990,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -3039,14 +3039,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
diff --git a/src/test/isolation/specs/stats.spec b/src/test/isolation/specs/stats.spec
index 5b922d788c..53d78f7db1 100644
--- a/src/test/isolation/specs/stats.spec
+++ b/src/test/isolation/specs/stats.spec
@@ -93,14 +93,14 @@ step s1_table_drop { DROP TABLE test_stat_tab; }
 
 step s1_table_stats {
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 }
diff --git a/src/test/recovery/t/029_stats_restart.pl b/src/test/recovery/t/029_stats_restart.pl
index 1bf7b568cc..c25634d33f 100644
--- a/src/test/recovery/t/029_stats_restart.pl
+++ b/src/test/recovery/t/029_stats_restart.pl
@@ -43,8 +43,8 @@ my $sect = "initial";
 is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist");
 is(have_stats('function', $dboid, $funcoid),
 	't', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
-	't', "$sect: relation stats do exist");
+is(have_stats('table', $dboid, $tableoid),
+	't', "$sect: table stats do exist");
 
 # regular shutdown
 $node->stop();
@@ -67,8 +67,8 @@ $sect = "copy";
 is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist");
 is(have_stats('function', $dboid, $funcoid),
 	't', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
-	't', "$sect: relation stats do exist");
+is(have_stats('table', $dboid, $tableoid),
+	't', "$sect: table stats do exist");
 
 $node->stop('immediate');
 
@@ -84,8 +84,8 @@ $sect = "post immediate";
 is(have_stats('database', $dboid, 0), 'f', "$sect: db stats do not exist");
 is(have_stats('function', $dboid, $funcoid),
 	'f', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
-	'f', "$sect: relation stats do not exist");
+is(have_stats('table', $dboid, $tableoid),
+	'f', "$sect: table stats do not exist");
 
 # get rid of backup statsfile
 unlink $statsfile or die "cannot unlink $statsfile $!";
@@ -98,8 +98,8 @@ $sect = "post immediate, new";
 is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist");
 is(have_stats('function', $dboid, $funcoid),
 	't', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
-	't', "$sect: relation stats do exist");
+is(have_stats('table', $dboid, $tableoid),
+	't', "$sect: table stats do exist");
 
 # regular shutdown
 $node->stop();
@@ -117,8 +117,7 @@ $sect = "invalid_overwrite";
 is(have_stats('database', $dboid, 0), 'f', "$sect: db stats do not exist");
 is(have_stats('function', $dboid, $funcoid),
 	'f', "$sect: function stats do not exist");
-is(have_stats('relation', $dboid, $tableoid),
-	'f', "$sect: relation stats do not exist");
+is(have_stats('table', $dboid, $tableoid), 'f', "$sect: table do not exist");
 
 
 ## check invalid stats file starting with valid contents, but followed by
@@ -133,8 +132,8 @@ $sect = "invalid_append";
 is(have_stats('database', $dboid, 0), 'f', "$sect: db stats do not exist");
 is(have_stats('function', $dboid, $funcoid),
 	'f', "$sect: function stats do not exist");
-is(have_stats('relation', $dboid, $tableoid),
-	'f', "$sect: relation stats do not exist");
+is(have_stats('table', $dboid, $tableoid),
+	'f', "$sect: table stats do not exist");
 
 
 ## checks related to stats persistency around restarts and resets
diff --git a/src/test/recovery/t/030_stats_cleanup_replica.pl b/src/test/recovery/t/030_stats_cleanup_replica.pl
index cc92ddbb52..1e78b13cf9 100644
--- a/src/test/recovery/t/030_stats_cleanup_replica.pl
+++ b/src/test/recovery/t/030_stats_cleanup_replica.pl
@@ -185,7 +185,7 @@ sub test_standby_func_tab_stats_status
 	my %stats;
 
 	$stats{rel} = $node_standby->safe_psql($connect_db,
-		"SELECT pg_stat_have_stats('relation', $dboid, $tableoid)");
+		"SELECT pg_stat_have_stats('table', $dboid, $tableoid)");
 	$stats{func} = $node_standby->safe_psql($connect_db,
 		"SELECT pg_stat_have_stats('function', $dboid, $funcoid)");
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 532ea36990..c2b9f41bf2 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1767,10 +1767,10 @@ pg_stat_all_indexes| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
     i.relname AS indexrelname,
-    pg_stat_get_numscans(i.oid) AS idx_scan,
-    pg_stat_get_lastscan(i.oid) AS last_idx_scan,
-    pg_stat_get_tuples_returned(i.oid) AS idx_tup_read,
-    pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch
+    pg_stat_get_ind_numscans(i.oid) AS idx_scan,
+    pg_stat_get_ind_lastscan(i.oid) AS last_idx_scan,
+    pg_stat_get_ind_tuples_returned(i.oid) AS idx_tup_read,
+    pg_stat_get_ind_tuples_fetched(i.oid) AS idx_tup_fetch
    FROM (((pg_class c
      JOIN pg_index x ON ((c.oid = x.indrelid)))
      JOIN pg_class i ON ((i.oid = x.indexrelid)))
@@ -1779,28 +1779,28 @@ pg_stat_all_indexes| SELECT c.oid AS relid,
 pg_stat_all_tables| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
-    pg_stat_get_numscans(c.oid) AS seq_scan,
-    pg_stat_get_lastscan(c.oid) AS last_seq_scan,
-    pg_stat_get_tuples_returned(c.oid) AS seq_tup_read,
-    (sum(pg_stat_get_numscans(i.indexrelid)))::bigint AS idx_scan,
-    max(pg_stat_get_lastscan(i.indexrelid)) AS last_idx_scan,
-    ((sum(pg_stat_get_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_tuples_fetched(c.oid)) AS idx_tup_fetch,
-    pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins,
-    pg_stat_get_tuples_updated(c.oid) AS n_tup_upd,
-    pg_stat_get_tuples_deleted(c.oid) AS n_tup_del,
-    pg_stat_get_tuples_hot_updated(c.oid) AS n_tup_hot_upd,
-    pg_stat_get_live_tuples(c.oid) AS n_live_tup,
-    pg_stat_get_dead_tuples(c.oid) AS n_dead_tup,
-    pg_stat_get_mod_since_analyze(c.oid) AS n_mod_since_analyze,
-    pg_stat_get_ins_since_vacuum(c.oid) AS n_ins_since_vacuum,
-    pg_stat_get_last_vacuum_time(c.oid) AS last_vacuum,
-    pg_stat_get_last_autovacuum_time(c.oid) AS last_autovacuum,
-    pg_stat_get_last_analyze_time(c.oid) AS last_analyze,
-    pg_stat_get_last_autoanalyze_time(c.oid) AS last_autoanalyze,
-    pg_stat_get_vacuum_count(c.oid) AS vacuum_count,
-    pg_stat_get_autovacuum_count(c.oid) AS autovacuum_count,
-    pg_stat_get_analyze_count(c.oid) AS analyze_count,
-    pg_stat_get_autoanalyze_count(c.oid) AS autoanalyze_count
+    pg_stat_get_tab_numscans(c.oid) AS seq_scan,
+    pg_stat_get_tab_lastscan(c.oid) AS last_seq_scan,
+    pg_stat_get_tab_tuples_returned(c.oid) AS seq_tup_read,
+    (sum(pg_stat_get_ind_numscans(i.indexrelid)))::bigint AS idx_scan,
+    max(pg_stat_get_ind_lastscan(i.indexrelid)) AS last_idx_scan,
+    ((sum(pg_stat_get_ind_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_tab_tuples_fetched(c.oid)) AS idx_tup_fetch,
+    pg_stat_get_tab_tuples_inserted(c.oid) AS n_tup_ins,
+    pg_stat_get_tab_tuples_updated(c.oid) AS n_tup_upd,
+    pg_stat_get_tab_tuples_deleted(c.oid) AS n_tup_del,
+    pg_stat_get_tab_tuples_hot_updated(c.oid) AS n_tup_hot_upd,
+    pg_stat_get_tab_live_tuples(c.oid) AS n_live_tup,
+    pg_stat_get_tab_dead_tuples(c.oid) AS n_dead_tup,
+    pg_stat_get_tab_mod_since_analyze(c.oid) AS n_mod_since_analyze,
+    pg_stat_get_tab_ins_since_vacuum(c.oid) AS n_ins_since_vacuum,
+    pg_stat_get_tab_last_vacuum_time(c.oid) AS last_vacuum,
+    pg_stat_get_tab_last_autovacuum_time(c.oid) AS last_autovacuum,
+    pg_stat_get_tab_last_analyze_time(c.oid) AS last_analyze,
+    pg_stat_get_tab_last_autoanalyze_time(c.oid) AS last_autoanalyze,
+    pg_stat_get_tab_vacuum_count(c.oid) AS vacuum_count,
+    pg_stat_get_tab_autovacuum_count(c.oid) AS autovacuum_count,
+    pg_stat_get_tab_analyze_count(c.oid) AS analyze_count,
+    pg_stat_get_tab_autoanalyze_count(c.oid) AS autoanalyze_count
    FROM ((pg_class c
      LEFT JOIN pg_index i ON ((c.oid = i.indrelid)))
      LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
@@ -2224,9 +2224,9 @@ pg_stat_wal_receiver| SELECT s.pid,
 pg_stat_xact_all_tables| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
-    pg_stat_get_xact_numscans(c.oid) AS seq_scan,
+    pg_stat_get_tab_xact_numscans(c.oid) AS seq_scan,
     pg_stat_get_xact_tuples_returned(c.oid) AS seq_tup_read,
-    (sum(pg_stat_get_xact_numscans(i.indexrelid)))::bigint AS idx_scan,
+    (sum(pg_stat_get_ind_xact_numscans(i.indexrelid)))::bigint AS idx_scan,
     ((sum(pg_stat_get_xact_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_xact_tuples_fetched(c.oid)) AS idx_tup_fetch,
     pg_stat_get_xact_tuples_inserted(c.oid) AS n_tup_ins,
     pg_stat_get_xact_tuples_updated(c.oid) AS n_tup_upd,
@@ -2277,8 +2277,8 @@ pg_statio_all_indexes| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
     i.relname AS indexrelname,
-    (pg_stat_get_blocks_fetched(i.oid) - pg_stat_get_blocks_hit(i.oid)) AS idx_blks_read,
-    pg_stat_get_blocks_hit(i.oid) AS idx_blks_hit
+    (pg_stat_get_ind_blocks_fetched(i.oid) - pg_stat_get_ind_blocks_hit(i.oid)) AS idx_blks_read,
+    pg_stat_get_ind_blocks_hit(i.oid) AS idx_blks_hit
    FROM (((pg_class c
      JOIN pg_index x ON ((c.oid = x.indrelid)))
      JOIN pg_class i ON ((i.oid = x.indexrelid)))
@@ -2287,31 +2287,31 @@ pg_statio_all_indexes| SELECT c.oid AS relid,
 pg_statio_all_sequences| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
-    (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS blks_read,
-    pg_stat_get_blocks_hit(c.oid) AS blks_hit
+    (pg_stat_get_ind_blocks_fetched(c.oid) - pg_stat_get_tab_blocks_hit(c.oid)) AS blks_read,
+    pg_stat_get_tab_blocks_hit(c.oid) AS blks_hit
    FROM (pg_class c
      LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
   WHERE (c.relkind = 'S'::"char");
 pg_statio_all_tables| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
-    (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS heap_blks_read,
-    pg_stat_get_blocks_hit(c.oid) AS heap_blks_hit,
+    (pg_stat_get_tab_blocks_fetched(c.oid) - pg_stat_get_tab_blocks_hit(c.oid)) AS heap_blks_read,
+    pg_stat_get_tab_blocks_hit(c.oid) AS heap_blks_hit,
     i.idx_blks_read,
     i.idx_blks_hit,
-    (pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid)) AS toast_blks_read,
-    pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit,
+    (pg_stat_get_tab_blocks_fetched(t.oid) - pg_stat_get_tab_blocks_hit(t.oid)) AS toast_blks_read,
+    pg_stat_get_tab_blocks_hit(t.oid) AS toast_blks_hit,
     x.idx_blks_read AS tidx_blks_read,
     x.idx_blks_hit AS tidx_blks_hit
    FROM ((((pg_class c
      LEFT JOIN pg_class t ON ((c.reltoastrelid = t.oid)))
      LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
-     LEFT JOIN LATERAL ( SELECT (sum((pg_stat_get_blocks_fetched(pg_index.indexrelid) - pg_stat_get_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
-            (sum(pg_stat_get_blocks_hit(pg_index.indexrelid)))::bigint AS idx_blks_hit
+     LEFT JOIN LATERAL ( SELECT (sum((pg_stat_get_ind_blocks_fetched(pg_index.indexrelid) - pg_stat_get_ind_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
+            (sum(pg_stat_get_ind_blocks_hit(pg_index.indexrelid)))::bigint AS idx_blks_hit
            FROM pg_index
           WHERE (pg_index.indrelid = c.oid)) i ON (true))
-     LEFT JOIN LATERAL ( SELECT (sum((pg_stat_get_blocks_fetched(pg_index.indexrelid) - pg_stat_get_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
-            (sum(pg_stat_get_blocks_hit(pg_index.indexrelid)))::bigint AS idx_blks_hit
+     LEFT JOIN LATERAL ( SELECT (sum((pg_stat_get_ind_blocks_fetched(pg_index.indexrelid) - pg_stat_get_ind_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
+            (sum(pg_stat_get_ind_blocks_hit(pg_index.indexrelid)))::bigint AS idx_blks_hit
            FROM pg_index
           WHERE (pg_index.indrelid = t.oid)) x ON (true))
   WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]));
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 1d84407a03..d5ee0f4845 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -151,6 +151,117 @@ FROM prevstats AS pr;
 
 COMMIT;
 ----
+-- Basic tests for toast
+---
+CREATE TABLE stats_toast(stuff text);
+ALTER TABLE stats_toast ALTER COLUMN stuff SET STORAGE EXTERNAL;
+INSERT INTO stats_toast VALUES (repeat('a',1000000));
+SELECT count(*) FROM stats_toast WHERE stuff like '%a%';
+ count 
+-------
+     1
+(1 row)
+
+-- ensure pending stats are flushed
+SELECT pg_stat_force_next_flush();
+ pg_stat_force_next_flush 
+--------------------------
+ 
+(1 row)
+
+select toast_blks_read > 0 as toast_blks_read, toast_blks_hit > 0 as toast_blks_hit,
+       tidx_blks_read > 0 as tidx_blks_read, tidx_blks_hit > 0 as tidx_blks_hit,
+       toast_blks_hit >= toast_blks_read,
+       tidx_blks_hit >= tidx_blks_read
+   from pg_statio_all_tables
+ where relname = 'stats_toast';
+ toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit | ?column? | ?column? 
+-----------------+----------------+----------------+---------------+----------+----------
+ t               | t              | t              | t             | t        | t
+(1 row)
+
+----
+-- Basic tests for partition
+---
+CREATE TABLE stats_partition (
+    id1         int not null,
+    id2         int not null
+) PARTITION BY RANGE (id2);
+CREATE TABLE stats_partition_5 PARTITION OF stats_partition
+    FOR VALUES FROM (0) TO (5);
+CREATE TABLE stats_partition_20000 PARTITION OF stats_partition
+    FOR VALUES FROM (5) TO (20001);
+CREATE INDEX ON stats_partition (id2);
+insert into stats_partition select a,a from generate_series(0,20000) a;
+SET enable_seqscan TO off;
+SET enable_bitmapscan TO off;
+select * from stats_partition where id2 = 2000;
+ id1  | id2  
+------+------
+ 2000 | 2000
+(1 row)
+
+select * from stats_partition where id2 = 2;
+ id1 | id2 
+-----+-----
+   2 |   2
+(1 row)
+
+-- ensure pending stats are flushed
+SELECT pg_stat_force_next_flush();
+ pg_stat_force_next_flush 
+--------------------------
+ 
+(1 row)
+
+select relname, indexrelname, idx_scan > 0 as idx_scan, idx_tup_read > 0 as idx_tup_read,
+       idx_tup_fetch > 0 as idx_tup_fetch
+   from pg_stat_all_indexes
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+        relname        |         indexrelname          | idx_scan | idx_tup_read | idx_tup_fetch 
+-----------------------+-------------------------------+----------+--------------+---------------
+ stats_partition_20000 | stats_partition_20000_id2_idx | t        | t            | t
+ stats_partition_5     | stats_partition_5_id2_idx     | t        | t            | t
+(2 rows)
+
+select relname, indexrelname, idx_blks_read > 0 as idx_blks_read,
+       idx_blks_hit > 0 as idx_blks_hit
+   from pg_statio_all_indexes
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+        relname        |         indexrelname          | idx_blks_read | idx_blks_hit 
+-----------------------+-------------------------------+---------------+--------------
+ stats_partition_20000 | stats_partition_20000_id2_idx | t             | t
+ stats_partition_5     | stats_partition_5_id2_idx     | t             | t
+(2 rows)
+
+select relname,seq_scan > 0 as seq_scan, seq_tup_read > 0 as seq_tup_read,
+       idx_scan > 0 as idx_scan, idx_tup_fetch > 0 as idx_tup_fetch
+   from pg_stat_all_tables
+  where relname like '%stats_partition%'
+  order by relname COLLATE "C";
+        relname        | seq_scan | seq_tup_read | idx_scan | idx_tup_fetch 
+-----------------------+----------+--------------+----------+---------------
+ stats_partition       | f        | f            | f        | f
+ stats_partition_20000 | t        | f            | t        | t
+ stats_partition_5     | t        | f            | t        | t
+(3 rows)
+
+select relname, heap_blks_read > 0 as heap_blks_read, heap_blks_hit > 0 as heap_blks_hit,
+       idx_blks_read > 0 as idx_blks_read, idx_blks_hit > 0 as idx_blks_hit
+   from pg_statio_all_tables
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+        relname        | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit 
+-----------------------+----------------+---------------+---------------+--------------
+ stats_partition_20000 | t              | t             | t             | t
+ stats_partition_5     | t              | t             | t             | t
+(2 rows)
+
+SET enable_seqscan TO on;
+SET enable_bitmapscan TO on;
+----
 -- Basic tests for track_functions
 ---
 CREATE FUNCTION stats_test_func1() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$;
@@ -357,17 +468,17 @@ SELECT pg_stat_force_next_flush();
  
 (1 row)
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           1
 (1 row)
 
 DROP TABLE drop_stats_test;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       0
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           0
 (1 row)
 
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid);
@@ -378,18 +489,18 @@ SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid);
 
 -- check that rollback protects against having stats dropped and that local
 -- modifications don't pose a problem
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
-(1 row)
-
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
- pg_stat_get_tuples_inserted 
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_live_tuples 
 -----------------------------
                            1
 (1 row)
 
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_tuples_inserted 
+---------------------------------
+                               1
+(1 row)
+
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
  pg_stat_get_xact_tuples_inserted 
 ----------------------------------
@@ -418,29 +529,29 @@ SELECT pg_stat_force_next_flush();
  
 (1 row)
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           1
 (1 row)
 
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
- pg_stat_get_tuples_inserted 
------------------------------
-                           2
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_tuples_inserted 
+---------------------------------
+                               2
 (1 row)
 
 -- transactional drop
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           1
 (1 row)
 
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
- pg_stat_get_tuples_inserted 
------------------------------
-                           2
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_tuples_inserted 
+---------------------------------
+                               2
 (1 row)
 
 BEGIN;
@@ -465,23 +576,23 @@ SELECT pg_stat_force_next_flush();
  
 (1 row)
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       0
-(1 row)
-
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
- pg_stat_get_tuples_inserted 
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_live_tuples 
 -----------------------------
                            0
 (1 row)
 
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_tuples_inserted 
+---------------------------------
+                               0
+(1 row)
+
 -- savepoint rollback (2 levels)
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           1
 (1 row)
 
 BEGIN;
@@ -510,17 +621,17 @@ SELECT pg_stat_force_next_flush();
  
 (1 row)
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       3
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           3
 (1 row)
 
 -- savepoint rolback (1 level)
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       3
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           3
 (1 row)
 
 BEGIN;
@@ -529,17 +640,17 @@ DROP TABLE drop_stats_test_subxact;
 SAVEPOINT sp2;
 ROLLBACK TO SAVEPOINT sp1;
 COMMIT;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       3
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           3
 (1 row)
 
 -- and now actually drop
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       3
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           3
 (1 row)
 
 BEGIN;
@@ -548,10 +659,10 @@ DROP TABLE drop_stats_test_subxact;
 SAVEPOINT sp2;
 RELEASE SAVEPOINT sp1;
 COMMIT;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       0
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           0
 (1 row)
 
 DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4;
@@ -1021,21 +1132,21 @@ select a from stats_test_tab1 where a = 3;
  3
 (1 row)
 
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
 (1 row)
 
 -- pg_stat_have_stats returns false for dropped index with stats
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
 (1 row)
 
 DROP index stats_test_idx1;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  f
@@ -1051,14 +1162,14 @@ select a from stats_test_tab1 where a = 3;
  3
 (1 row)
 
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
 (1 row)
 
 ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  f
@@ -1073,7 +1184,7 @@ select a from stats_test_tab1 where a = 3;
  3
 (1 row)
 
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
@@ -1081,7 +1192,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
 
 REINDEX index CONCURRENTLY stats_test_idx1;
 -- false for previous oid
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  f
@@ -1089,7 +1200,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
 
 -- true for new oid
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
@@ -1097,7 +1208,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns true for a rolled back drop index with stats
 BEGIN;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
@@ -1105,7 +1216,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
 
 DROP index stats_test_idx1;
 ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index b4d6753c71..1e9ae74b2a 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -126,6 +126,77 @@ FROM prevstats AS pr;
 
 COMMIT;
 
+----
+-- Basic tests for toast
+---
+CREATE TABLE stats_toast(stuff text);
+ALTER TABLE stats_toast ALTER COLUMN stuff SET STORAGE EXTERNAL;
+INSERT INTO stats_toast VALUES (repeat('a',1000000));
+SELECT count(*) FROM stats_toast WHERE stuff like '%a%';
+
+-- ensure pending stats are flushed
+SELECT pg_stat_force_next_flush();
+
+select toast_blks_read > 0 as toast_blks_read, toast_blks_hit > 0 as toast_blks_hit,
+       tidx_blks_read > 0 as tidx_blks_read, tidx_blks_hit > 0 as tidx_blks_hit,
+       toast_blks_hit >= toast_blks_read,
+       tidx_blks_hit >= tidx_blks_read
+   from pg_statio_all_tables
+ where relname = 'stats_toast';
+
+----
+-- Basic tests for partition
+---
+CREATE TABLE stats_partition (
+    id1         int not null,
+    id2         int not null
+) PARTITION BY RANGE (id2);
+
+CREATE TABLE stats_partition_5 PARTITION OF stats_partition
+    FOR VALUES FROM (0) TO (5);
+
+CREATE TABLE stats_partition_20000 PARTITION OF stats_partition
+    FOR VALUES FROM (5) TO (20001);
+
+CREATE INDEX ON stats_partition (id2);
+
+insert into stats_partition select a,a from generate_series(0,20000) a;
+
+SET enable_seqscan TO off;
+SET enable_bitmapscan TO off;
+
+select * from stats_partition where id2 = 2000;
+select * from stats_partition where id2 = 2;
+-- ensure pending stats are flushed
+SELECT pg_stat_force_next_flush();
+
+select relname, indexrelname, idx_scan > 0 as idx_scan, idx_tup_read > 0 as idx_tup_read,
+       idx_tup_fetch > 0 as idx_tup_fetch
+   from pg_stat_all_indexes
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+
+select relname, indexrelname, idx_blks_read > 0 as idx_blks_read,
+       idx_blks_hit > 0 as idx_blks_hit
+   from pg_statio_all_indexes
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+
+select relname,seq_scan > 0 as seq_scan, seq_tup_read > 0 as seq_tup_read,
+       idx_scan > 0 as idx_scan, idx_tup_fetch > 0 as idx_tup_fetch
+   from pg_stat_all_tables
+  where relname like '%stats_partition%'
+  order by relname COLLATE "C";
+
+select relname, heap_blks_read > 0 as heap_blks_read, heap_blks_hit > 0 as heap_blks_hit,
+       idx_blks_read > 0 as idx_blks_read, idx_blks_hit > 0 as idx_blks_hit
+   from pg_statio_all_tables
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+
+SET enable_seqscan TO on;
+SET enable_bitmapscan TO on;
+
 ----
 -- Basic tests for track_functions
 ---
@@ -218,15 +289,15 @@ SELECT 'drop_stats_test_subxact'::regclass::oid AS drop_stats_test_subxact_oid \
 
 SELECT pg_stat_force_next_flush();
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_oid);
 DROP TABLE drop_stats_test;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_oid);
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid);
 
 -- check that rollback protects against having stats dropped and that local
 -- modifications don't pose a problem
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
 BEGIN;
 INSERT INTO drop_stats_test_xact DEFAULT VALUES;
@@ -235,12 +306,12 @@ DROP TABLE drop_stats_test_xact;
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
 ROLLBACK;
 SELECT pg_stat_force_next_flush();
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
 
 -- transactional drop
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
 BEGIN;
 INSERT INTO drop_stats_test_xact DEFAULT VALUES;
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
@@ -248,11 +319,11 @@ DROP TABLE drop_stats_test_xact;
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
 COMMIT;
 SELECT pg_stat_force_next_flush();
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
 
 -- savepoint rollback (2 levels)
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 BEGIN;
 INSERT INTO drop_stats_test_subxact DEFAULT VALUES;
 SAVEPOINT sp1;
@@ -264,27 +335,27 @@ ROLLBACK TO SAVEPOINT sp2;
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid);
 COMMIT;
 SELECT pg_stat_force_next_flush();
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 
 -- savepoint rolback (1 level)
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 BEGIN;
 SAVEPOINT sp1;
 DROP TABLE drop_stats_test_subxact;
 SAVEPOINT sp2;
 ROLLBACK TO SAVEPOINT sp1;
 COMMIT;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 
 -- and now actually drop
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 BEGIN;
 SAVEPOINT sp1;
 DROP TABLE drop_stats_test_subxact;
 SAVEPOINT sp2;
 RELEASE SAVEPOINT sp1;
 COMMIT;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 
 DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4;
 DROP TABLE prevstats;
@@ -493,40 +564,40 @@ CREATE index stats_test_idx1 on stats_test_tab1(a);
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
 SET enable_seqscan TO off;
 select a from stats_test_tab1 where a = 3;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns false for dropped index with stats
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 DROP index stats_test_idx1;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns false for rolled back index creation
 BEGIN;
 CREATE index stats_test_idx1 on stats_test_tab1(a);
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
 select a from stats_test_tab1 where a = 3;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns true for reindex CONCURRENTLY
 CREATE index stats_test_idx1 on stats_test_tab1(a);
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
 select a from stats_test_tab1 where a = 3;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 REINDEX index CONCURRENTLY stats_test_idx1;
 -- false for previous oid
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 -- true for new oid
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns true for a rolled back drop index with stats
 BEGIN;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 DROP index stats_test_idx1;
 ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- put enable_seqscan back to on
 SET enable_seqscan TO on;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 58daeca831..f9009263bc 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2008,10 +2008,11 @@ PgStatShared_Common
 PgStatShared_Database
 PgStatShared_Function
 PgStatShared_HashEntry
-PgStatShared_Relation
+PgStatShared_Index
 PgStatShared_ReplSlot
 PgStatShared_SLRU
 PgStatShared_Subscription
+PgStatShared_Table
 PgStatShared_Wal
 PgStat_ArchiverStats
 PgStat_BackendFunctionEntry
@@ -2025,6 +2026,7 @@ PgStat_FetchConsistency
 PgStat_FunctionCallUsage
 PgStat_FunctionCounts
 PgStat_HashKey
+PgStat_IndexStatus
 PgStat_Kind
 PgStat_KindInfo
 PgStat_LocalState


Attachments:

  [text/plain] v5-0001-split_tables_indexes_stats.patch (159.5K, ../[email protected]/2-v5-0001-split_tables_indexes_stats.patch)
  download | inline diff:
diff --git a/src/backend/access/common/relation.c b/src/backend/access/common/relation.c
index 382a42ff7d..259bd06aed 100644
--- a/src/backend/access/common/relation.c
+++ b/src/backend/access/common/relation.c
@@ -73,7 +73,10 @@ relation_open(Oid relationId, LOCKMODE lockmode)
 	if (RelationUsesLocalBuffers(r))
 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
 
-	pgstat_init_relation(r);
+	if (r->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_init_index(r);
+	else
+		pgstat_init_table(r);
 
 	return r;
 }
@@ -123,7 +126,10 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
 	if (RelationUsesLocalBuffers(r))
 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
 
-	pgstat_init_relation(r);
+	if (r->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_init_index(r);
+	else
+		pgstat_init_table(r);
 
 	return r;
 }
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index dc303995e5..ceebc79302 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -590,7 +590,7 @@ index_fetch_heap(IndexScanDesc scan, TupleTableSlot *slot)
 									&scan->xs_heap_continue, &all_dead);
 
 	if (found)
-		pgstat_count_heap_fetch(scan->indexRelation);
+		pgstat_count_index_fetch(scan->indexRelation);
 
 	/*
 	 * If we scanned a whole HOT chain and found only dead tuples, tell index
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index bdd413f01b..d5b71fdd1e 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -404,7 +404,10 @@ heap_create(const char *relname,
 									 reltablespace);
 
 	/* ensure that stats are dropped if transaction aborts */
-	pgstat_create_relation(rel);
+	if (rel->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_create_index(rel);
+	else
+		pgstat_create_table(rel);
 
 	return rel;
 }
@@ -1853,7 +1856,7 @@ heap_drop_with_catalog(Oid relid)
 		RelationDropStorage(rel);
 
 	/* ensure that stats are dropped if transaction commits */
-	pgstat_drop_relation(rel);
+	pgstat_drop_table(rel);
 
 	/*
 	 * Close relcache entry, but *keep* AccessExclusiveLock on the relation
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 61f1d3926a..28b94fef7f 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1752,7 +1752,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
 	changeDependenciesOn(RelationRelationId, oldIndexId, newIndexId);
 
 	/* copy over statistics from old to new index */
-	pgstat_copy_relation_stats(newClassRel, oldClassRel);
+	pgstat_copy_index_stats(newClassRel, oldClassRel);
 
 	/* Copy data of pg_statistic from the old index to the new one */
 	CopyStatistics(oldIndexId, newIndexId);
@@ -2326,7 +2326,7 @@ index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode)
 		RelationDropStorage(userIndexRelation);
 
 	/* ensure that stats are dropped if transaction commits */
-	pgstat_drop_relation(userIndexRelation);
+	pgstat_drop_index(userIndexRelation);
 
 	/*
 	 * Close and flush the index's relcache entry, to ensure relcache doesn't
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 2d8104b090..a612ae81ed 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -655,29 +655,29 @@ CREATE VIEW pg_stat_all_tables AS
             C.oid AS relid,
             N.nspname AS schemaname,
             C.relname AS relname,
-            pg_stat_get_numscans(C.oid) AS seq_scan,
-            pg_stat_get_lastscan(C.oid) AS last_seq_scan,
-            pg_stat_get_tuples_returned(C.oid) AS seq_tup_read,
-            sum(pg_stat_get_numscans(I.indexrelid))::bigint AS idx_scan,
-            max(pg_stat_get_lastscan(I.indexrelid)) AS last_idx_scan,
-            sum(pg_stat_get_tuples_fetched(I.indexrelid))::bigint +
-            pg_stat_get_tuples_fetched(C.oid) AS idx_tup_fetch,
-            pg_stat_get_tuples_inserted(C.oid) AS n_tup_ins,
-            pg_stat_get_tuples_updated(C.oid) AS n_tup_upd,
-            pg_stat_get_tuples_deleted(C.oid) AS n_tup_del,
-            pg_stat_get_tuples_hot_updated(C.oid) AS n_tup_hot_upd,
-            pg_stat_get_live_tuples(C.oid) AS n_live_tup,
-            pg_stat_get_dead_tuples(C.oid) AS n_dead_tup,
-            pg_stat_get_mod_since_analyze(C.oid) AS n_mod_since_analyze,
-            pg_stat_get_ins_since_vacuum(C.oid) AS n_ins_since_vacuum,
-            pg_stat_get_last_vacuum_time(C.oid) as last_vacuum,
-            pg_stat_get_last_autovacuum_time(C.oid) as last_autovacuum,
-            pg_stat_get_last_analyze_time(C.oid) as last_analyze,
-            pg_stat_get_last_autoanalyze_time(C.oid) as last_autoanalyze,
-            pg_stat_get_vacuum_count(C.oid) AS vacuum_count,
-            pg_stat_get_autovacuum_count(C.oid) AS autovacuum_count,
-            pg_stat_get_analyze_count(C.oid) AS analyze_count,
-            pg_stat_get_autoanalyze_count(C.oid) AS autoanalyze_count
+            pg_stat_get_tab_numscans(C.oid) AS seq_scan,
+            pg_stat_get_tab_lastscan(C.oid) AS last_seq_scan,
+            pg_stat_get_tab_tuples_returned(C.oid) AS seq_tup_read,
+            sum(pg_stat_get_ind_numscans(I.indexrelid))::bigint AS idx_scan,
+            max(pg_stat_get_ind_lastscan(I.indexrelid)) AS last_idx_scan,
+            sum(pg_stat_get_ind_tuples_fetched(I.indexrelid))::bigint +
+            pg_stat_get_tab_tuples_fetched(C.oid) AS idx_tup_fetch,
+            pg_stat_get_tab_tuples_inserted(C.oid) AS n_tup_ins,
+            pg_stat_get_tab_tuples_updated(C.oid) AS n_tup_upd,
+            pg_stat_get_tab_tuples_deleted(C.oid) AS n_tup_del,
+            pg_stat_get_tab_tuples_hot_updated(C.oid) AS n_tup_hot_upd,
+            pg_stat_get_tab_live_tuples(C.oid) AS n_live_tup,
+            pg_stat_get_tab_dead_tuples(C.oid) AS n_dead_tup,
+            pg_stat_get_tab_mod_since_analyze(C.oid) AS n_mod_since_analyze,
+            pg_stat_get_tab_ins_since_vacuum(C.oid) AS n_ins_since_vacuum,
+            pg_stat_get_tab_last_vacuum_time(C.oid) as last_vacuum,
+            pg_stat_get_tab_last_autovacuum_time(C.oid) as last_autovacuum,
+            pg_stat_get_tab_last_analyze_time(C.oid) as last_analyze,
+            pg_stat_get_tab_last_autoanalyze_time(C.oid) as last_autoanalyze,
+            pg_stat_get_tab_vacuum_count(C.oid) AS vacuum_count,
+            pg_stat_get_tab_autovacuum_count(C.oid) AS autovacuum_count,
+            pg_stat_get_tab_analyze_count(C.oid) AS analyze_count,
+            pg_stat_get_tab_autoanalyze_count(C.oid) AS autoanalyze_count
     FROM pg_class C LEFT JOIN
          pg_index I ON C.oid = I.indrelid
          LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
@@ -689,9 +689,9 @@ CREATE VIEW pg_stat_xact_all_tables AS
             C.oid AS relid,
             N.nspname AS schemaname,
             C.relname AS relname,
-            pg_stat_get_xact_numscans(C.oid) AS seq_scan,
+            pg_stat_get_tab_xact_numscans(C.oid) AS seq_scan,
             pg_stat_get_xact_tuples_returned(C.oid) AS seq_tup_read,
-            sum(pg_stat_get_xact_numscans(I.indexrelid))::bigint AS idx_scan,
+            sum(pg_stat_get_ind_xact_numscans(I.indexrelid))::bigint AS idx_scan,
             sum(pg_stat_get_xact_tuples_fetched(I.indexrelid))::bigint +
             pg_stat_get_xact_tuples_fetched(C.oid) AS idx_tup_fetch,
             pg_stat_get_xact_tuples_inserted(C.oid) AS n_tup_ins,
@@ -729,31 +729,31 @@ CREATE VIEW pg_statio_all_tables AS
             C.oid AS relid,
             N.nspname AS schemaname,
             C.relname AS relname,
-            pg_stat_get_blocks_fetched(C.oid) -
-                    pg_stat_get_blocks_hit(C.oid) AS heap_blks_read,
-            pg_stat_get_blocks_hit(C.oid) AS heap_blks_hit,
+            pg_stat_get_tab_blocks_fetched(C.oid) -
+                    pg_stat_get_tab_blocks_hit(C.oid) AS heap_blks_read,
+            pg_stat_get_tab_blocks_hit(C.oid) AS heap_blks_hit,
             I.idx_blks_read AS idx_blks_read,
             I.idx_blks_hit AS idx_blks_hit,
-            pg_stat_get_blocks_fetched(T.oid) -
-                    pg_stat_get_blocks_hit(T.oid) AS toast_blks_read,
-            pg_stat_get_blocks_hit(T.oid) AS toast_blks_hit,
+            pg_stat_get_tab_blocks_fetched(T.oid) -
+                    pg_stat_get_tab_blocks_hit(T.oid) AS toast_blks_read,
+            pg_stat_get_tab_blocks_hit(T.oid) AS toast_blks_hit,
             X.idx_blks_read AS tidx_blks_read,
             X.idx_blks_hit AS tidx_blks_hit
     FROM pg_class C LEFT JOIN
             pg_class T ON C.reltoastrelid = T.oid
             LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
             LEFT JOIN LATERAL (
-              SELECT sum(pg_stat_get_blocks_fetched(indexrelid) -
-                         pg_stat_get_blocks_hit(indexrelid))::bigint
+              SELECT sum(pg_stat_get_ind_blocks_fetched(indexrelid) -
+                         pg_stat_get_ind_blocks_hit(indexrelid))::bigint
                      AS idx_blks_read,
-                     sum(pg_stat_get_blocks_hit(indexrelid))::bigint
+                     sum(pg_stat_get_ind_blocks_hit(indexrelid))::bigint
                      AS idx_blks_hit
               FROM pg_index WHERE indrelid = C.oid ) I ON true
             LEFT JOIN LATERAL (
-              SELECT sum(pg_stat_get_blocks_fetched(indexrelid) -
-                         pg_stat_get_blocks_hit(indexrelid))::bigint
+              SELECT sum(pg_stat_get_ind_blocks_fetched(indexrelid) -
+                         pg_stat_get_ind_blocks_hit(indexrelid))::bigint
                      AS idx_blks_read,
-                     sum(pg_stat_get_blocks_hit(indexrelid))::bigint
+                     sum(pg_stat_get_ind_blocks_hit(indexrelid))::bigint
                      AS idx_blks_hit
               FROM pg_index WHERE indrelid = T.oid ) X ON true
     WHERE C.relkind IN ('r', 't', 'm');
@@ -775,10 +775,10 @@ CREATE VIEW pg_stat_all_indexes AS
             N.nspname AS schemaname,
             C.relname AS relname,
             I.relname AS indexrelname,
-            pg_stat_get_numscans(I.oid) AS idx_scan,
-            pg_stat_get_lastscan(I.oid) AS last_idx_scan,
-            pg_stat_get_tuples_returned(I.oid) AS idx_tup_read,
-            pg_stat_get_tuples_fetched(I.oid) AS idx_tup_fetch
+            pg_stat_get_ind_numscans(I.oid) AS idx_scan,
+            pg_stat_get_ind_lastscan(I.oid) AS last_idx_scan,
+            pg_stat_get_ind_tuples_returned(I.oid) AS idx_tup_read,
+            pg_stat_get_ind_tuples_fetched(I.oid) AS idx_tup_fetch
     FROM pg_class C JOIN
             pg_index X ON C.oid = X.indrelid JOIN
             pg_class I ON I.oid = X.indexrelid
@@ -802,9 +802,9 @@ CREATE VIEW pg_statio_all_indexes AS
             N.nspname AS schemaname,
             C.relname AS relname,
             I.relname AS indexrelname,
-            pg_stat_get_blocks_fetched(I.oid) -
-                    pg_stat_get_blocks_hit(I.oid) AS idx_blks_read,
-            pg_stat_get_blocks_hit(I.oid) AS idx_blks_hit
+            pg_stat_get_ind_blocks_fetched(I.oid) -
+                    pg_stat_get_ind_blocks_hit(I.oid) AS idx_blks_read,
+            pg_stat_get_ind_blocks_hit(I.oid) AS idx_blks_hit
     FROM pg_class C JOIN
             pg_index X ON C.oid = X.indrelid JOIN
             pg_class I ON I.oid = X.indexrelid
@@ -826,9 +826,9 @@ CREATE VIEW pg_statio_all_sequences AS
             C.oid AS relid,
             N.nspname AS schemaname,
             C.relname AS relname,
-            pg_stat_get_blocks_fetched(C.oid) -
-                    pg_stat_get_blocks_hit(C.oid) AS blks_read,
-            pg_stat_get_blocks_hit(C.oid) AS blks_hit
+            pg_stat_get_ind_blocks_fetched(C.oid) -
+                    pg_stat_get_tab_blocks_hit(C.oid) AS blks_read,
+            pg_stat_get_tab_blocks_hit(C.oid) AS blks_hit
     FROM pg_class C
             LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
     WHERE C.relkind = 'S';
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 73d30bf619..f1a7a8aa8d 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -776,11 +776,19 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
 	 * Read the buffer, and update pgstat counters to reflect a cache hit or
 	 * miss.
 	 */
-	pgstat_count_buffer_read(reln);
+	if (reln->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_count_index_buffer_read(reln);
+	else
+		pgstat_count_table_buffer_read(reln);
 	buf = ReadBuffer_common(RelationGetSmgr(reln), reln->rd_rel->relpersistence,
 							forkNum, blockNum, mode, strategy, &hit);
 	if (hit)
-		pgstat_count_buffer_hit(reln);
+	{
+		if (reln->rd_rel->relkind == RELKIND_INDEX)
+			pgstat_count_index_buffer_hit(reln);
+		else
+			pgstat_count_table_buffer_hit(reln);
+	}
 	return buf;
 }
 
diff --git a/src/backend/utils/activity/Makefile b/src/backend/utils/activity/Makefile
index a2e8507fd6..7441f4ce85 100644
--- a/src/backend/utils/activity/Makefile
+++ b/src/backend/utils/activity/Makefile
@@ -22,11 +22,12 @@ OBJS = \
 	pgstat_checkpointer.o \
 	pgstat_database.o \
 	pgstat_function.o \
-	pgstat_relation.o \
+	pgstat_index.o \
 	pgstat_replslot.o \
 	pgstat_shmem.o \
 	pgstat_slru.o \
 	pgstat_subscription.o \
+	pgstat_table.o \
 	pgstat_wal.o \
 	pgstat_xact.o \
 	wait_event.o
diff --git a/src/backend/utils/activity/meson.build b/src/backend/utils/activity/meson.build
index 5b3b558a67..e6bf3c59b6 100644
--- a/src/backend/utils/activity/meson.build
+++ b/src/backend/utils/activity/meson.build
@@ -7,11 +7,12 @@ backend_sources += files(
   'pgstat_checkpointer.c',
   'pgstat_database.c',
   'pgstat_function.c',
-  'pgstat_relation.c',
+  'pgstat_index.c',
   'pgstat_replslot.c',
   'pgstat_shmem.c',
   'pgstat_slru.c',
   'pgstat_subscription.c',
+  'pgstat_table.c',
   'pgstat_wal.c',
   'pgstat_xact.c',
   'wait_event.c',
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index 1ebe3bbf29..d49a5ea4bb 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -72,10 +72,11 @@
  * - pgstat_checkpointer.c
  * - pgstat_database.c
  * - pgstat_function.c
- * - pgstat_relation.c
+ * - pgstat_index.c
  * - pgstat_replslot.c
  * - pgstat_slru.c
  * - pgstat_subscription.c
+ * - pgstat_table.c
  * - pgstat_wal.c
  *
  * Whenever possible infrastructure files should not contain code related to
@@ -269,18 +270,32 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = {
 		.reset_timestamp_cb = pgstat_database_reset_timestamp_cb,
 	},
 
-	[PGSTAT_KIND_RELATION] = {
-		.name = "relation",
+	[PGSTAT_KIND_TABLE] = {
+		.name = "table",
 
 		.fixed_amount = false,
 
-		.shared_size = sizeof(PgStatShared_Relation),
-		.shared_data_off = offsetof(PgStatShared_Relation, stats),
-		.shared_data_len = sizeof(((PgStatShared_Relation *) 0)->stats),
+		.shared_size = sizeof(PgStatShared_Table),
+		.shared_data_off = offsetof(PgStatShared_Table, stats),
+		.shared_data_len = sizeof(((PgStatShared_Table *) 0)->stats),
 		.pending_size = sizeof(PgStat_TableStatus),
 
-		.flush_pending_cb = pgstat_relation_flush_cb,
-		.delete_pending_cb = pgstat_relation_delete_pending_cb,
+		.flush_pending_cb = pgstat_table_flush_cb,
+		.delete_pending_cb = pgstat_table_delete_pending_cb,
+	},
+
+	[PGSTAT_KIND_INDEX] = {
+		.name = "index",
+
+		.fixed_amount = false,
+
+		.shared_size = sizeof(PgStatShared_Index),
+		.shared_data_off = offsetof(PgStatShared_Index, stats),
+		.shared_data_len = sizeof(((PgStatShared_Index *) 0)->stats),
+		.pending_size = sizeof(PgStat_IndexStatus),
+
+		.flush_pending_cb = pgstat_index_flush_cb,
+		.delete_pending_cb = pgstat_index_delete_pending_cb,
 	},
 
 	[PGSTAT_KIND_FUNCTION] = {
diff --git a/src/backend/utils/activity/pgstat_index.c b/src/backend/utils/activity/pgstat_index.c
new file mode 100644
index 0000000000..13b48b11e5
--- /dev/null
+++ b/src/backend/utils/activity/pgstat_index.c
@@ -0,0 +1,297 @@
+/* -------------------------------------------------------------------------
+ *
+ * pgstat_index.c
+ *	  Implementation of index statistics.
+ *
+ * This file contains the implementation of function index. It is kept
+ * separate from pgstat.c to enforce the line between the statistics access /
+ * storage implementation and the details about individual types of
+ * statistics.
+ *
+ * Copyright (c) 2001-2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/backend/utils/activity/pgstat_index.c
+ * -------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/xact.h"
+#include "utils/pgstat_internal.h"
+#include "utils/rel.h"
+#include "catalog/catalog.h"
+
+static PgStat_IndexStatus *pgstat_prep_index_pending(Oid rel_id, bool isshared);
+
+/*
+ * Copy stats between indexes. This is used for things like REINDEX
+ * CONCURRENTLY.
+ */
+void
+pgstat_copy_index_stats(Relation dst, Relation src)
+{
+	PgStat_StatIndEntry *srcstats;
+	PgStatShared_Index *dstshstats;
+	PgStat_EntryRef *dst_ref;
+
+	srcstats = pgstat_fetch_stat_indentry_ext(src->rd_rel->relisshared,
+											  RelationGetRelid(src));
+	if (!srcstats)
+		return;
+
+	dst_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_INDEX,
+										  dst->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
+										  RelationGetRelid(dst),
+										  false);
+
+	dstshstats = (PgStatShared_Index *) dst_ref->shared_stats;
+	dstshstats->stats = *srcstats;
+
+	pgstat_unlock_entry(dst_ref);
+}
+
+/*
+ * Initialize a relcache entry to count access statistics.  Called whenever an
+ * index is opened.
+ *
+ * We assume that a relcache entry's pgstatind_info field is zeroed by relcache.c
+ * when the relcache entry is made; thereafter it is long-lived data.
+ *
+ * This does not create a reference to a stats entry in shared memory, nor
+ * allocate memory for the pending stats. That happens in
+ * pgstat_assoc_index().
+ */
+void
+pgstat_init_index(Relation rel)
+{
+	/*
+	 * We only count stats for indexes
+	 */
+	Assert(rel->rd_rel->relkind == RELKIND_INDEX);
+
+	if (!pgstat_track_counts)
+	{
+		if (rel->pgstatind_info != NULL)
+			pgstat_unlink_index(rel);
+
+		/* We're not counting at all */
+		rel->pgstat_enabled = false;
+		rel->pgstatind_info = NULL;
+		return;
+	}
+
+	rel->pgstat_enabled = true;
+}
+
+/*
+ * Prepare for statistics for this index to be collected.
+ *
+ * This ensures we have a reference to the stats entry before stats can be
+ * generated. That is important because an index drop in another
+ * connection could otherwise lead to the stats entry being dropped, which then
+ * later would get recreated when flushing stats.
+ *
+ * This is separate from pgstat_init_index() as it is not uncommon for
+ * relcache entries to be opened without ever getting stats reported.
+ */
+void
+pgstat_assoc_index(Relation rel)
+{
+	Assert(rel->pgstat_enabled);
+	Assert(rel->pgstatind_info == NULL);
+
+	/* Else find or make the PgStat_IndexStatus entry, and update link */
+	rel->pgstatind_info = pgstat_prep_index_pending(RelationGetRelid(rel),
+													rel->rd_rel->relisshared);
+
+	/* don't allow link a stats to multiple relcache entries */
+	Assert(rel->pgstatind_info->relation == NULL);
+
+	/* mark this relation as the owner */
+	rel->pgstatind_info->relation = rel;
+}
+
+/*
+ * Break the mutual link between a relcache entry and pending index stats entry.
+ * This must be called whenever one end of the link is removed.
+ */
+void
+pgstat_unlink_index(Relation rel)
+{
+
+	if (rel->pgstatind_info == NULL)
+		return;
+
+	/* link sanity check for the index stats */
+	if (rel->pgstatind_info)
+	{
+		Assert(rel->pgstatind_info->relation == rel);
+		rel->pgstatind_info->relation = NULL;
+		rel->pgstatind_info = NULL;
+	}
+}
+
+/*
+ * Ensure that index stats are dropped if transaction aborts.
+ */
+void
+pgstat_create_index(Relation rel)
+{
+	pgstat_create_transactional(PGSTAT_KIND_INDEX,
+								rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
+								RelationGetRelid(rel));
+}
+
+/*
+ * Ensure that index stats are dropped if transaction commits.
+ */
+void
+pgstat_drop_index(Relation rel)
+{
+	pgstat_drop_transactional(PGSTAT_KIND_INDEX,
+							  rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
+							  RelationGetRelid(rel));
+}
+
+/*
+ * Support function for the SQL-callable pgstat* functions. Returns
+ * the collected statistics for one index or NULL. NULL doesn't mean
+ * that the index doesn't exist, just that there are no statistics, so the
+ * caller is better off to report ZERO instead.
+ */
+PgStat_StatIndEntry *
+pgstat_fetch_stat_indentry(Oid relid)
+{
+	return pgstat_fetch_stat_indentry_ext(IsSharedRelation(relid), relid);
+}
+
+/*
+ * More efficient version of pgstat_fetch_stat_indentry(), allowing to specify
+ * whether the to-be-accessed index is shared or not.
+ */
+PgStat_StatIndEntry *
+pgstat_fetch_stat_indentry_ext(bool shared, Oid reloid)
+{
+	Oid			dboid = (shared ? InvalidOid : MyDatabaseId);
+
+	return (PgStat_StatIndEntry *)
+		pgstat_fetch_entry(PGSTAT_KIND_INDEX, dboid, reloid);
+}
+
+/*
+ * find any existing PgStat_IndexStatus entry for rel
+ *
+ * Find any existing PgStat_IndexStatus entry for rel_id in the current
+ * database. If not found, try finding from shared indexes.
+ *
+ * If no entry found, return NULL, don't create a new one
+ */
+PgStat_IndexStatus *
+find_indstat_entry(Oid rel_id)
+{
+	PgStat_EntryRef *entry_ref;
+
+	entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_INDEX, MyDatabaseId, rel_id);
+	if (!entry_ref)
+		entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_INDEX, InvalidOid, rel_id);
+
+	if (entry_ref)
+		return entry_ref->pending;
+	return NULL;
+}
+
+/*
+ * Flush out pending stats for the entry
+ *
+ * If nowait is true, this function returns false if lock could not
+ * immediately acquired, otherwise true is returned.
+ *
+ * Some of the stats are copied to the corresponding pending database stats
+ * entry when successfully flushing.
+ */
+bool
+pgstat_index_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
+{
+	static const PgStat_IndexCounts all_zeroes;
+	Oid			dboid;
+
+	PgStat_IndexStatus *lstats; /* pending stats entry  */
+	PgStatShared_Index *shrelcomstats;
+	PgStat_StatIndEntry *indentry;	/* index entry of shared stats */
+	PgStat_StatDBEntry *dbentry;	/* pending database entry */
+
+	dboid = entry_ref->shared_entry->key.dboid;
+	lstats = (PgStat_IndexStatus *) entry_ref->pending;
+	shrelcomstats = (PgStatShared_Index *) entry_ref->shared_stats;
+
+	/*
+	 * Ignore entries that didn't accumulate any actual counts, such as
+	 * indexes that were opened by the planner but not used.
+	 */
+	if (memcmp(&lstats->i_counts, &all_zeroes,
+			   sizeof(PgStat_IndexCounts)) == 0)
+	{
+		return true;
+	}
+
+	if (!pgstat_lock_entry(entry_ref, nowait))
+		return false;
+
+	/* add the values to the shared entry. */
+	indentry = &shrelcomstats->stats;
+
+	indentry->numscans += lstats->i_counts.i_numscans;
+
+	if (lstats->i_counts.i_numscans)
+	{
+		TimestampTz t = GetCurrentTransactionStopTimestamp();
+
+		if (t > indentry->lastscan)
+			indentry->lastscan = t;
+	}
+	indentry->tuples_returned += lstats->i_counts.i_tuples_returned;
+	indentry->tuples_fetched += lstats->i_counts.i_tuples_fetched;
+	indentry->blocks_fetched += lstats->i_counts.i_blocks_fetched;
+	indentry->blocks_hit += lstats->i_counts.i_blocks_hit;
+
+	pgstat_unlock_entry(entry_ref);
+
+	/* The entry was successfully flushed, add the same to database stats */
+	dbentry = pgstat_prep_database_pending(dboid);
+	dbentry->n_tuples_returned += lstats->i_counts.i_tuples_returned;
+	dbentry->n_tuples_fetched += lstats->i_counts.i_tuples_fetched;
+	dbentry->n_blocks_fetched += lstats->i_counts.i_blocks_fetched;
+	dbentry->n_blocks_hit += lstats->i_counts.i_blocks_hit;
+
+	return true;
+}
+
+void
+pgstat_index_delete_pending_cb(PgStat_EntryRef *entry_ref)
+{
+	PgStat_IndexStatus *pending = (PgStat_IndexStatus *) entry_ref->pending;
+
+	if (pending->relation)
+		pgstat_unlink_index(pending->relation);
+}
+
+/*
+ * Find or create a PgStat_IndexStatus entry for rel. New entry is created and
+ * initialized if not exists.
+ */
+static PgStat_IndexStatus *
+pgstat_prep_index_pending(Oid rel_id, bool isshared)
+{
+	PgStat_EntryRef *entry_ref;
+	PgStat_IndexStatus *pending;
+
+	entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_INDEX,
+										  isshared ? InvalidOid : MyDatabaseId,
+										  rel_id, NULL);
+	pending = entry_ref->pending;
+	pending->r_id = rel_id;
+	pending->r_shared = isshared;
+
+	return pending;
+}
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_table.c
similarity index 75%
rename from src/backend/utils/activity/pgstat_relation.c
rename to src/backend/utils/activity/pgstat_table.c
index a9c05153d9..b9c29bd7c2 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_table.c
@@ -1,9 +1,9 @@
 /* -------------------------------------------------------------------------
  *
- * pgstat_relation.c
- *	  Implementation of relation statistics.
+ * pgstat_table.c
+ *	  Implementation of table statistics.
  *
- * This file contains the implementation of function relation. It is kept
+ * This file contains the implementation of function table. It is kept
  * separate from pgstat.c to enforce the line between the statistics access /
  * storage implementation and the details about individual types of
  * statistics.
@@ -11,7 +11,7 @@
  * Copyright (c) 2001-2022, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  src/backend/utils/activity/pgstat_relation.c
+ *	  src/backend/utils/activity/pgstat_table.c
  * -------------------------------------------------------------------------
  */
 
@@ -44,74 +44,48 @@ typedef struct TwoPhasePgStatRecord
 } TwoPhasePgStatRecord;
 
 
-static PgStat_TableStatus *pgstat_prep_relation_pending(Oid rel_id, bool isshared);
-static void add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level);
-static void ensure_tabstat_xact_level(PgStat_TableStatus *pgstat_info);
+static PgStat_TableStatus *pgstat_prep_table_pending(Oid rel_id, bool isshared);
+static void add_tabstat_xact_level(PgStat_TableStatus *pgstattab_info, int nest_level);
+static void ensure_tabstat_xact_level(PgStat_TableStatus *pgstattab_info);
 static void save_truncdrop_counters(PgStat_TableXactStatus *trans, bool is_drop);
 static void restore_truncdrop_counters(PgStat_TableXactStatus *trans);
 
-
-/*
- * Copy stats between relations. This is used for things like REINDEX
- * CONCURRENTLY.
- */
-void
-pgstat_copy_relation_stats(Relation dst, Relation src)
-{
-	PgStat_StatTabEntry *srcstats;
-	PgStatShared_Relation *dstshstats;
-	PgStat_EntryRef *dst_ref;
-
-	srcstats = pgstat_fetch_stat_tabentry_ext(src->rd_rel->relisshared,
-											  RelationGetRelid(src));
-	if (!srcstats)
-		return;
-
-	dst_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION,
-										  dst->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
-										  RelationGetRelid(dst),
-										  false);
-
-	dstshstats = (PgStatShared_Relation *) dst_ref->shared_stats;
-	dstshstats->stats = *srcstats;
-
-	pgstat_unlock_entry(dst_ref);
-}
-
 /*
  * Initialize a relcache entry to count access statistics.  Called whenever a
- * relation is opened.
+ * table is opened.
  *
- * We assume that a relcache entry's pgstat_info field is zeroed by relcache.c
+ * We assume that a relcache entry's pgstattab_info field is zeroed by relcache.c
  * when the relcache entry is made; thereafter it is long-lived data.
  *
  * This does not create a reference to a stats entry in shared memory, nor
  * allocate memory for the pending stats. That happens in
- * pgstat_assoc_relation().
+ * pgstat_assoc_table().
  */
 void
-pgstat_init_relation(Relation rel)
+pgstat_init_table(Relation rel)
 {
 	char		relkind = rel->rd_rel->relkind;
 
+	Assert(relkind != RELKIND_INDEX);
+
 	/*
 	 * We only count stats for relations with storage and partitioned tables
 	 */
 	if (!RELKIND_HAS_STORAGE(relkind) && relkind != RELKIND_PARTITIONED_TABLE)
 	{
 		rel->pgstat_enabled = false;
-		rel->pgstat_info = NULL;
+		rel->pgstattab_info = NULL;
 		return;
 	}
 
 	if (!pgstat_track_counts)
 	{
-		if (rel->pgstat_info)
-			pgstat_unlink_relation(rel);
+		if (rel->pgstattab_info != NULL)
+			pgstat_unlink_table(rel);
 
 		/* We're not counting at all */
 		rel->pgstat_enabled = false;
-		rel->pgstat_info = NULL;
+		rel->pgstattab_info = NULL;
 		return;
 	}
 
@@ -119,89 +93,92 @@ pgstat_init_relation(Relation rel)
 }
 
 /*
- * Prepare for statistics for this relation to be collected.
+ * Prepare for statistics for this table to be collected.
  *
  * This ensures we have a reference to the stats entry before stats can be
- * generated. That is important because a relation drop in another connection
+ * generated. That is important because a table drop in another connection
  * could otherwise lead to the stats entry being dropped, which then later
  * would get recreated when flushing stats.
  *
- * This is separate from pgstat_init_relation() as it is not uncommon for
+ * This is separate from pgstat_init_table() as it is not uncommon for
  * relcache entries to be opened without ever getting stats reported.
  */
 void
-pgstat_assoc_relation(Relation rel)
+pgstat_assoc_table(Relation rel)
 {
 	Assert(rel->pgstat_enabled);
-	Assert(rel->pgstat_info == NULL);
+	Assert(rel->pgstattab_info == NULL);
 
 	/* Else find or make the PgStat_TableStatus entry, and update link */
-	rel->pgstat_info = pgstat_prep_relation_pending(RelationGetRelid(rel),
+	rel->pgstattab_info = pgstat_prep_table_pending(RelationGetRelid(rel),
 													rel->rd_rel->relisshared);
 
 	/* don't allow link a stats to multiple relcache entries */
-	Assert(rel->pgstat_info->relation == NULL);
+	Assert(rel->pgstattab_info->relation == NULL);
 
 	/* mark this relation as the owner */
-	rel->pgstat_info->relation = rel;
+	rel->pgstattab_info->relation = rel;
 }
 
 /*
- * Break the mutual link between a relcache entry and pending stats entry.
+ * Break the mutual link between a relcache entry and pending table stats entry.
  * This must be called whenever one end of the link is removed.
  */
 void
-pgstat_unlink_relation(Relation rel)
+pgstat_unlink_table(Relation rel)
 {
-	/* remove the link to stats info if any */
-	if (rel->pgstat_info == NULL)
+
+	if (rel->pgstattab_info == NULL)
 		return;
 
-	/* link sanity check */
-	Assert(rel->pgstat_info->relation == rel);
-	rel->pgstat_info->relation = NULL;
-	rel->pgstat_info = NULL;
+	/* link sanity check for the table stats */
+	if (rel->pgstattab_info)
+	{
+		Assert(rel->pgstattab_info->relation == rel);
+		rel->pgstattab_info->relation = NULL;
+		rel->pgstattab_info = NULL;
+	}
 }
 
 /*
- * Ensure that stats are dropped if transaction aborts.
+ * Ensure that table stats are dropped if transaction aborts.
  */
 void
-pgstat_create_relation(Relation rel)
+pgstat_create_table(Relation rel)
 {
-	pgstat_create_transactional(PGSTAT_KIND_RELATION,
+	pgstat_create_transactional(PGSTAT_KIND_TABLE,
 								rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
 								RelationGetRelid(rel));
 }
 
 /*
- * Ensure that stats are dropped if transaction commits.
+ * Ensure that table stats are dropped if transaction commits.
  */
 void
-pgstat_drop_relation(Relation rel)
+pgstat_drop_table(Relation rel)
 {
 	int			nest_level = GetCurrentTransactionNestLevel();
-	PgStat_TableStatus *pgstat_info;
+	PgStat_TableStatus *pgstattab_info;
 
-	pgstat_drop_transactional(PGSTAT_KIND_RELATION,
+	pgstat_drop_transactional(PGSTAT_KIND_TABLE,
 							  rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
 							  RelationGetRelid(rel));
 
-	if (!pgstat_should_count_relation(rel))
+	if (!pgstat_should_count_table(rel))
 		return;
 
 	/*
 	 * Transactionally set counters to 0. That ensures that accesses to
 	 * pg_stat_xact_all_tables inside the transaction show 0.
 	 */
-	pgstat_info = rel->pgstat_info;
-	if (pgstat_info->trans &&
-		pgstat_info->trans->nest_level == nest_level)
+	pgstattab_info = rel->pgstattab_info;
+	if (pgstattab_info->trans &&
+		pgstattab_info->trans->nest_level == nest_level)
 	{
-		save_truncdrop_counters(pgstat_info->trans, true);
-		pgstat_info->trans->tuples_inserted = 0;
-		pgstat_info->trans->tuples_updated = 0;
-		pgstat_info->trans->tuples_deleted = 0;
+		save_truncdrop_counters(pgstattab_info->trans, true);
+		pgstattab_info->trans->tuples_inserted = 0;
+		pgstattab_info->trans->tuples_updated = 0;
+		pgstattab_info->trans->tuples_deleted = 0;
 	}
 }
 
@@ -213,7 +190,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 					 PgStat_Counter livetuples, PgStat_Counter deadtuples)
 {
 	PgStat_EntryRef *entry_ref;
-	PgStatShared_Relation *shtabentry;
+	PgStatShared_Table *shtabentry;
 	PgStat_StatTabEntry *tabentry;
 	Oid			dboid = (shared ? InvalidOid : MyDatabaseId);
 	TimestampTz ts;
@@ -225,10 +202,10 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	ts = GetCurrentTimestamp();
 
 	/* block acquiring lock for the same reason as pgstat_report_autovac() */
-	entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION,
+	entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_TABLE,
 											dboid, tableoid, false);
 
-	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
+	shtabentry = (PgStatShared_Table *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
 	tabentry->live_tuples = livetuples;
@@ -272,7 +249,7 @@ pgstat_report_analyze(Relation rel,
 					  bool resetcounter)
 {
 	PgStat_EntryRef *entry_ref;
-	PgStatShared_Relation *shtabentry;
+	PgStatShared_Table *shtabentry;
 	PgStat_StatTabEntry *tabentry;
 	Oid			dboid = (rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId);
 
@@ -291,31 +268,31 @@ pgstat_report_analyze(Relation rel,
 	 *
 	 * Waste no time on partitioned tables, though.
 	 */
-	if (pgstat_should_count_relation(rel) &&
+	if (pgstat_should_count_table(rel) &&
 		rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
 	{
 		PgStat_TableXactStatus *trans;
 
-		for (trans = rel->pgstat_info->trans; trans; trans = trans->upper)
+		for (trans = rel->pgstattab_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;
+		deadtuples -= rel->pgstattab_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);
 	}
 
 	/* block acquiring lock for the same reason as pgstat_report_autovac() */
-	entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION, dboid,
+	entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_TABLE, dboid,
 											RelationGetRelid(rel),
 											false);
 	/* can't get dropped while accessed */
 	Assert(entry_ref != NULL && entry_ref->shared_stats != NULL);
 
-	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
+	shtabentry = (PgStatShared_Table *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
 	tabentry->live_tuples = livetuples;
@@ -349,12 +326,12 @@ pgstat_report_analyze(Relation rel,
 void
 pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		ensure_tabstat_xact_level(pgstat_info);
-		pgstat_info->trans->tuples_inserted += n;
+		ensure_tabstat_xact_level(pgstattab_info);
+		pgstattab_info->trans->tuples_inserted += n;
 	}
 }
 
@@ -364,16 +341,16 @@ pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
 void
 pgstat_count_heap_update(Relation rel, bool hot)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		ensure_tabstat_xact_level(pgstat_info);
-		pgstat_info->trans->tuples_updated++;
+		ensure_tabstat_xact_level(pgstattab_info);
+		pgstattab_info->trans->tuples_updated++;
 
 		/* t_tuples_hot_updated is nontransactional, so just advance it */
 		if (hot)
-			pgstat_info->t_counts.t_tuples_hot_updated++;
+			pgstattab_info->t_counts.t_tuples_hot_updated++;
 	}
 }
 
@@ -383,12 +360,12 @@ pgstat_count_heap_update(Relation rel, bool hot)
 void
 pgstat_count_heap_delete(Relation rel)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		ensure_tabstat_xact_level(pgstat_info);
-		pgstat_info->trans->tuples_deleted++;
+		ensure_tabstat_xact_level(pgstattab_info);
+		pgstattab_info->trans->tuples_deleted++;
 	}
 }
 
@@ -398,15 +375,15 @@ pgstat_count_heap_delete(Relation rel)
 void
 pgstat_count_truncate(Relation rel)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		ensure_tabstat_xact_level(pgstat_info);
-		save_truncdrop_counters(pgstat_info->trans, false);
-		pgstat_info->trans->tuples_inserted = 0;
-		pgstat_info->trans->tuples_updated = 0;
-		pgstat_info->trans->tuples_deleted = 0;
+		ensure_tabstat_xact_level(pgstattab_info);
+		save_truncdrop_counters(pgstattab_info->trans, false);
+		pgstattab_info->trans->tuples_inserted = 0;
+		pgstattab_info->trans->tuples_updated = 0;
+		pgstattab_info->trans->tuples_deleted = 0;
 	}
 }
 
@@ -421,11 +398,11 @@ pgstat_count_truncate(Relation rel)
 void
 pgstat_update_heap_dead_tuples(Relation rel, int delta)
 {
-	if (pgstat_should_count_relation(rel))
+	if (pgstat_should_count_table(rel))
 	{
-		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+		PgStat_TableStatus *pgstattab_info = rel->pgstattab_info;
 
-		pgstat_info->t_counts.t_delta_dead_tuples -= delta;
+		pgstattab_info->t_counts.t_delta_dead_tuples -= delta;
 	}
 }
 
@@ -451,7 +428,7 @@ pgstat_fetch_stat_tabentry_ext(bool shared, Oid reloid)
 	Oid			dboid = (shared ? InvalidOid : MyDatabaseId);
 
 	return (PgStat_StatTabEntry *)
-		pgstat_fetch_entry(PGSTAT_KIND_RELATION, dboid, reloid);
+		pgstat_fetch_entry(PGSTAT_KIND_TABLE, dboid, reloid);
 }
 
 /*
@@ -467,9 +444,9 @@ find_tabstat_entry(Oid rel_id)
 {
 	PgStat_EntryRef *entry_ref;
 
-	entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, MyDatabaseId, rel_id);
+	entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_TABLE, MyDatabaseId, rel_id);
 	if (!entry_ref)
-		entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, InvalidOid, rel_id);
+		entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_TABLE, InvalidOid, rel_id);
 
 	if (entry_ref)
 		return entry_ref->pending;
@@ -477,7 +454,7 @@ find_tabstat_entry(Oid rel_id)
 }
 
 /*
- * Perform relation stats specific end-of-transaction work. Helper for
+ * Perform table stats specific end-of-transaction work. Helper for
  * AtEOXact_PgStat.
  *
  * Transfer transactional insert/update counts into the base tabstat entries.
@@ -485,7 +462,7 @@ find_tabstat_entry(Oid rel_id)
  * TopTransactionContext and will go away anyway.
  */
 void
-AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit)
+AtEOXact_PgStat_Tables(PgStat_SubXactStatus *xact_state, bool isCommit)
 {
 	PgStat_TableXactStatus *trans;
 
@@ -536,14 +513,14 @@ AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit)
 }
 
 /*
- * Perform relation stats specific end-of-sub-transaction work. Helper for
+ * Perform table stats specific end-of-sub-transaction work. Helper for
  * AtEOSubXact_PgStat.
  *
  * Transfer transactional insert/update counts into the next higher
  * subtransaction state.
  */
 void
-AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth)
+AtEOSubXact_PgStat_Tables(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth)
 {
 	PgStat_TableXactStatus *trans;
 	PgStat_TableXactStatus *next_trans;
@@ -620,11 +597,11 @@ AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, in
 }
 
 /*
- * Generate 2PC records for all the pending transaction-dependent relation
+ * Generate 2PC records for all the pending transaction-dependent table
  * stats.
  */
 void
-AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
+AtPrepare_PgStat_Tables(PgStat_SubXactStatus *xact_state)
 {
 	PgStat_TableXactStatus *trans;
 
@@ -659,10 +636,10 @@ AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
  * reported to the stats system immediately, while the effects on live and
  * dead tuple counts are preserved in the 2PC state file.
  *
- * Note: AtEOXact_PgStat_Relations is not called during PREPARE.
+ * Note: AtEOXact_PgStat_Tables is not called during PREPARE.
  */
 void
-PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
+PostPrepare_PgStat_Tables(PgStat_SubXactStatus *xact_state)
 {
 	PgStat_TableXactStatus *trans;
 
@@ -685,27 +662,27 @@ pgstat_twophase_postcommit(TransactionId xid, uint16 info,
 						   void *recdata, uint32 len)
 {
 	TwoPhasePgStatRecord *rec = (TwoPhasePgStatRecord *) recdata;
-	PgStat_TableStatus *pgstat_info;
+	PgStat_TableStatus *pgstattab_info;
 
 	/* Find or create a tabstat entry for the rel */
-	pgstat_info = pgstat_prep_relation_pending(rec->t_id, rec->t_shared);
+	pgstattab_info = pgstat_prep_table_pending(rec->t_id, rec->t_shared);
 
 	/* Same math as in AtEOXact_PgStat, commit case */
-	pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
-	pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated;
-	pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
-	pgstat_info->t_counts.t_truncdropped = rec->t_truncdropped;
+	pgstattab_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
+	pgstattab_info->t_counts.t_tuples_updated += rec->tuples_updated;
+	pgstattab_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
+	pgstattab_info->t_counts.t_truncdropped = rec->t_truncdropped;
 	if (rec->t_truncdropped)
 	{
 		/* forget live/dead stats seen by backend thus far */
-		pgstat_info->t_counts.t_delta_live_tuples = 0;
-		pgstat_info->t_counts.t_delta_dead_tuples = 0;
+		pgstattab_info->t_counts.t_delta_live_tuples = 0;
+		pgstattab_info->t_counts.t_delta_dead_tuples = 0;
 	}
-	pgstat_info->t_counts.t_delta_live_tuples +=
+	pgstattab_info->t_counts.t_delta_live_tuples +=
 		rec->tuples_inserted - rec->tuples_deleted;
-	pgstat_info->t_counts.t_delta_dead_tuples +=
+	pgstattab_info->t_counts.t_delta_dead_tuples +=
 		rec->tuples_updated + rec->tuples_deleted;
-	pgstat_info->t_counts.t_changed_tuples +=
+	pgstattab_info->t_counts.t_changed_tuples +=
 		rec->tuples_inserted + rec->tuples_updated +
 		rec->tuples_deleted;
 }
@@ -721,10 +698,10 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info,
 						  void *recdata, uint32 len)
 {
 	TwoPhasePgStatRecord *rec = (TwoPhasePgStatRecord *) recdata;
-	PgStat_TableStatus *pgstat_info;
+	PgStat_TableStatus *pgstattab_info;
 
 	/* Find or create a tabstat entry for the rel */
-	pgstat_info = pgstat_prep_relation_pending(rec->t_id, rec->t_shared);
+	pgstattab_info = pgstat_prep_table_pending(rec->t_id, rec->t_shared);
 
 	/* Same math as in AtEOXact_PgStat, abort case */
 	if (rec->t_truncdropped)
@@ -733,10 +710,10 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info,
 		rec->tuples_updated = rec->updated_pre_truncdrop;
 		rec->tuples_deleted = rec->deleted_pre_truncdrop;
 	}
-	pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
-	pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated;
-	pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
-	pgstat_info->t_counts.t_delta_dead_tuples +=
+	pgstattab_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
+	pgstattab_info->t_counts.t_tuples_updated += rec->tuples_updated;
+	pgstattab_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
+	pgstattab_info->t_counts.t_delta_dead_tuples +=
 		rec->tuples_inserted + rec->tuples_updated;
 }
 
@@ -750,22 +727,21 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info,
  * entry when successfully flushing.
  */
 bool
-pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
+pgstat_table_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 {
 	static const PgStat_TableCounts all_zeroes;
 	Oid			dboid;
 	PgStat_TableStatus *lstats; /* pending stats entry  */
-	PgStatShared_Relation *shtabstats;
+	PgStatShared_Table *shtabstats;
 	PgStat_StatTabEntry *tabentry;	/* table entry of shared stats */
 	PgStat_StatDBEntry *dbentry;	/* pending database entry */
 
 	dboid = entry_ref->shared_entry->key.dboid;
 	lstats = (PgStat_TableStatus *) entry_ref->pending;
-	shtabstats = (PgStatShared_Relation *) entry_ref->shared_stats;
+	shtabstats = (PgStatShared_Table *) entry_ref->shared_stats;
 
 	/*
-	 * Ignore entries that didn't accumulate any actual counts, such as
-	 * indexes that were opened by the planner but not used.
+	 * Ignore entries that didn't accumulate any actual counts.
 	 */
 	if (memcmp(&lstats->t_counts, &all_zeroes,
 			   sizeof(PgStat_TableCounts)) == 0)
@@ -783,6 +759,7 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 	if (lstats->t_counts.t_numscans)
 	{
 		TimestampTz t = GetCurrentTransactionStopTimestamp();
+
 		if (t > tabentry->lastscan)
 			tabentry->lastscan = t;
 	}
@@ -831,12 +808,12 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 }
 
 void
-pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref)
+pgstat_table_delete_pending_cb(PgStat_EntryRef *entry_ref)
 {
 	PgStat_TableStatus *pending = (PgStat_TableStatus *) entry_ref->pending;
 
 	if (pending->relation)
-		pgstat_unlink_relation(pending->relation);
+		pgstat_unlink_table(pending->relation);
 }
 
 /*
@@ -844,12 +821,12 @@ pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref)
  * initialized if not exists.
  */
 static PgStat_TableStatus *
-pgstat_prep_relation_pending(Oid rel_id, bool isshared)
+pgstat_prep_table_pending(Oid rel_id, bool isshared)
 {
 	PgStat_EntryRef *entry_ref;
 	PgStat_TableStatus *pending;
 
-	entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_RELATION,
+	entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_TABLE,
 										  isshared ? InvalidOid : MyDatabaseId,
 										  rel_id, NULL);
 	pending = entry_ref->pending;
@@ -863,7 +840,7 @@ pgstat_prep_relation_pending(Oid rel_id, bool isshared)
  * add a new (sub)transaction state record
  */
 static void
-add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
+add_tabstat_xact_level(PgStat_TableStatus *pgstattab_info, int nest_level)
 {
 	PgStat_SubXactStatus *xact_state;
 	PgStat_TableXactStatus *trans;
@@ -879,24 +856,24 @@ add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
 		MemoryContextAllocZero(TopTransactionContext,
 							   sizeof(PgStat_TableXactStatus));
 	trans->nest_level = nest_level;
-	trans->upper = pgstat_info->trans;
-	trans->parent = pgstat_info;
+	trans->upper = pgstattab_info->trans;
+	trans->parent = pgstattab_info;
 	trans->next = xact_state->first;
 	xact_state->first = trans;
-	pgstat_info->trans = trans;
+	pgstattab_info->trans = trans;
 }
 
 /*
  * Add a new (sub)transaction record if needed.
  */
 static void
-ensure_tabstat_xact_level(PgStat_TableStatus *pgstat_info)
+ensure_tabstat_xact_level(PgStat_TableStatus *pgstattab_info)
 {
 	int			nest_level = GetCurrentTransactionNestLevel();
 
-	if (pgstat_info->trans == NULL ||
-		pgstat_info->trans->nest_level != nest_level)
-		add_tabstat_xact_level(pgstat_info, nest_level);
+	if (pgstattab_info->trans == NULL ||
+		pgstattab_info->trans->nest_level != nest_level)
+		add_tabstat_xact_level(pgstattab_info, nest_level);
 }
 
 /*
diff --git a/src/backend/utils/activity/pgstat_xact.c b/src/backend/utils/activity/pgstat_xact.c
index 5a3aca4aef..870f1b1103 100644
--- a/src/backend/utils/activity/pgstat_xact.c
+++ b/src/backend/utils/activity/pgstat_xact.c
@@ -51,7 +51,7 @@ AtEOXact_PgStat(bool isCommit, bool parallel)
 		Assert(xact_state->nest_level == 1);
 		Assert(xact_state->prev == NULL);
 
-		AtEOXact_PgStat_Relations(xact_state, isCommit);
+		AtEOXact_PgStat_Tables(xact_state, isCommit);
 		AtEOXact_PgStat_DroppedStats(xact_state, isCommit);
 	}
 	pgStatXactStack = NULL;
@@ -122,7 +122,7 @@ AtEOSubXact_PgStat(bool isCommit, int nestDepth)
 		/* delink xact_state from stack immediately to simplify reuse case */
 		pgStatXactStack = xact_state->prev;
 
-		AtEOSubXact_PgStat_Relations(xact_state, isCommit, nestDepth);
+		AtEOSubXact_PgStat_Tables(xact_state, isCommit, nestDepth);
 		AtEOSubXact_PgStat_DroppedStats(xact_state, isCommit, nestDepth);
 
 		pfree(xact_state);
@@ -197,7 +197,7 @@ AtPrepare_PgStat(void)
 		Assert(xact_state->nest_level == 1);
 		Assert(xact_state->prev == NULL);
 
-		AtPrepare_PgStat_Relations(xact_state);
+		AtPrepare_PgStat_Tables(xact_state);
 	}
 }
 
@@ -221,7 +221,7 @@ PostPrepare_PgStat(void)
 		Assert(xact_state->nest_level == 1);
 		Assert(xact_state->prev == NULL);
 
-		PostPrepare_PgStat_Relations(xact_state);
+		PostPrepare_PgStat_Tables(xact_state);
 	}
 	pgStatXactStack = NULL;
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 973979508d..dea762c116 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -36,106 +36,124 @@
 
 #define HAS_PGSTAT_PERMISSIONS(role)	 (has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role))
 
-#define PG_STAT_GET_RELENTRY_INT64(stat)						\
-Datum															\
-CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
-{																\
-	Oid			relid = PG_GETARG_OID(0);						\
-	int64		result;											\
-	PgStat_StatTabEntry *tabentry;								\
-																\
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)	\
-		result = 0;												\
-	else														\
-		result = (int64) (tabentry->stat);						\
-																\
-	PG_RETURN_INT64(result);									\
-}																\
+#define PG_STAT_GET_RELENTRY_INT64(Relkind,relkind,stat)				\
+Datum																	\
+pg_stat_get_##relkind##_##stat(PG_FUNCTION_ARGS)						\
+{																		\
+	Oid			relid = PG_GETARG_OID(0);								\
+	int64		result;													\
+	PgStat_Stat##Relkind##Entry *entry;									\
+																		\
+	if ((entry = pgstat_fetch_stat_##relkind##entry(relid)) == NULL)	\
+		result = 0;														\
+	else																\
+		result = (int64) (entry->stat);									\
+																		\
+	PG_RETURN_INT64(result);											\
+}
+
+/* pg_stat_get_tab_analyze_count */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,analyze_count);
+
+/* pg_stat_get_tab_autoanalyze_count */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,autoanalyze_count);
+
+/* pg_stat_get_tab_autovacuum_count */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,autovacuum_count);
+
+/* pg_stat_get_tab_blocks_fetched */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,blocks_fetched);
+
+/* pg_stat_get_tab_blocks_hit */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,blocks_hit);
+
+/* pg_stat_get_tab_dead_tuples */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,dead_tuples);
 
-/* pg_stat_get_analyze_count */
-PG_STAT_GET_RELENTRY_INT64(analyze_count);
+/* pg_stat_get_tab_ins_since_vacuum */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,ins_since_vacuum);
 
-/* pg_stat_get_autoanalyze_count */
-PG_STAT_GET_RELENTRY_INT64(autoanalyze_count);
+/* pg_stat_get_tab_live_tuples */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,live_tuples);
 
-/* pg_stat_get_autovacuum_count */
-PG_STAT_GET_RELENTRY_INT64(autovacuum_count);
+/* pg_stat_get_mod_since_analyze */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,mod_since_analyze);
 
-/* pg_stat_get_blocks_fetched */
-PG_STAT_GET_RELENTRY_INT64(blocks_fetched);
+/* pg_stat_get_tab_numscans */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,numscans);
 
-/* pg_stat_get_blocks_hit */
-PG_STAT_GET_RELENTRY_INT64(blocks_hit);
+/* pg_stat_get_tab_tuples_deleted */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_deleted);
 
-/* pg_stat_get_dead_tuples */
-PG_STAT_GET_RELENTRY_INT64(dead_tuples);
+/* pg_stat_get_tab_tuples_fetched */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_fetched);
 
-/* pg_stat_get_ins_since_vacuum */
-PG_STAT_GET_RELENTRY_INT64(ins_since_vacuum);
+/* pg_stat_get_tab_tuples_hot_updated */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_hot_updated);
 
-/* pg_stat_get_live_tuples */
-PG_STAT_GET_RELENTRY_INT64(live_tuples);
+/* pg_stat_get_tab_tuples_inserted */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_inserted);
 
-/* pg_stat_get_mods_since_analyze */
-PG_STAT_GET_RELENTRY_INT64(mod_since_analyze);
+/* pg_stat_get_tab_tuples_returned */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_returned);
 
-/* pg_stat_get_numscans */
-PG_STAT_GET_RELENTRY_INT64(numscans);
+/* pg_stat_get_tab_tuples_updated */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,tuples_updated);
 
-/* pg_stat_get_tuples_deleted */
-PG_STAT_GET_RELENTRY_INT64(tuples_deleted);
+/* pg_stat_get_tab_vacuum_count */
+PG_STAT_GET_RELENTRY_INT64(Tab,tab,vacuum_count);
 
-/* pg_stat_get_tuples_fetched */
-PG_STAT_GET_RELENTRY_INT64(tuples_fetched);
+/* pg_stat_get_ind_numscans */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,numscans);
 
-/* pg_stat_get_tuples_hot_updated */
-PG_STAT_GET_RELENTRY_INT64(tuples_hot_updated);
+/* pg_stat_get_ind_tuples_returned */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,tuples_returned);
 
-/* pg_stat_get_tuples_inserted */
-PG_STAT_GET_RELENTRY_INT64(tuples_inserted);
+/* pg_stat_get_ind_tuples_fetched */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,tuples_fetched);
 
-/* pg_stat_get_tuples_returned */
-PG_STAT_GET_RELENTRY_INT64(tuples_returned);
+/* pg_stat_get_ind_blocks_fetched */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,blocks_fetched);
 
-/* pg_stat_get_tuples_updated */
-PG_STAT_GET_RELENTRY_INT64(tuples_updated);
+/* pg_stat_get_ind_blocks_hit */
+PG_STAT_GET_RELENTRY_INT64(Ind,ind,blocks_hit);
 
-/* pg_stat_get_vacuum_count */
-PG_STAT_GET_RELENTRY_INT64(vacuum_count);
+#define PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Relkind,relkind,stat)			\
+Datum																	\
+pg_stat_get_##relkind##_##stat(PG_FUNCTION_ARGS)						\
+{																		\
+	Oid			relid = PG_GETARG_OID(0);								\
+	TimestampTz		result;												\
+	PgStat_Stat##Relkind##Entry *entry;									\
+																		\
+	if ((entry = pgstat_fetch_stat_##relkind##entry(relid)) == NULL)	\
+		result = 0;														\
+	else																\
+		result = entry->stat;											\
+																		\
+	if (result == 0)													\
+		PG_RETURN_NULL();												\
+	else																\
+		PG_RETURN_TIMESTAMPTZ(result);									\
+}
 
-#define PG_STAT_GET_RELENTRY_TIMESTAMPTZ(stat)					\
-Datum															\
-CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
-{																\
-	Oid			relid = PG_GETARG_OID(0);						\
-	TimestampTz result;											\
-	PgStat_StatTabEntry *tabentry;								\
-																\
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)	\
-		result = 0;												\
-	else														\
-		result = tabentry->stat;								\
-																\
-	if (result == 0)											\
-		PG_RETURN_NULL();										\
-	else														\
-		PG_RETURN_TIMESTAMPTZ(result);							\
-}																\
+/* pg_stat_get_tab_last_analyze_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,last_analyze_time);
 
-/* pg_stat_get_last_analyze_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_analyze_time);
+/* pg_stat_get_tab_last_autoanalyze_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,last_autoanalyze_time);
 
-/* pg_stat_get_last_autoanalyze_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autoanalyze_time);
+/* pg_stat_get_tab_last_autovacuum_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,last_autovacuum_time);
 
-/* pg_stat_get_last_autovacuum_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autovacuum_time);
+/* pg_stat_get_tab_last_vacuum_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,last_vacuum_time);
 
-/* pg_stat_get_last_vacuum_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_vacuum_time);
+/* pg_stat_get_tab_lastscan */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Tab,tab,lastscan);
 
-/* pg_stat_get_lastscan */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(lastscan);
+/* pg_stat_get_ind_lastscan */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(Ind,ind,lastscan);
 
 Datum
 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
@@ -1586,7 +1604,7 @@ pg_stat_get_slru(PG_FUNCTION_ARGS)
 }
 
 Datum
-pg_stat_get_xact_numscans(PG_FUNCTION_ARGS)
+pg_stat_get_tab_xact_numscans(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
@@ -1600,17 +1618,32 @@ pg_stat_get_xact_numscans(PG_FUNCTION_ARGS)
 	PG_RETURN_INT64(result);
 }
 
+Datum
+pg_stat_get_ind_xact_numscans(PG_FUNCTION_ARGS)
+{
+	Oid			relid = PG_GETARG_OID(0);
+	int64		result;
+	PgStat_IndexStatus *indentry;
+
+	if ((indentry = find_indstat_entry(relid)) == NULL)
+		result = 0;
+	else
+		result = (int64) (indentry->i_counts.i_numscans);
+
+	PG_RETURN_INT64(result);
+}
+
 Datum
 pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
-	PgStat_TableStatus *tabentry;
+	PgStat_IndexStatus *indentry;
 
-	if ((tabentry = find_tabstat_entry(relid)) == NULL)
+	if ((indentry = find_indstat_entry(relid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (tabentry->t_counts.t_tuples_returned);
+		result = (int64) (indentry->i_counts.i_tuples_returned);
 
 	PG_RETURN_INT64(result);
 }
@@ -1620,12 +1653,12 @@ pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
-	PgStat_TableStatus *tabentry;
+	PgStat_IndexStatus *indentry;
 
-	if ((tabentry = find_tabstat_entry(relid)) == NULL)
+	if ((indentry = find_indstat_entry(relid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (tabentry->t_counts.t_tuples_fetched);
+		result = (int64) (indentry->i_counts.i_tuples_fetched);
 
 	PG_RETURN_INT64(result);
 }
@@ -1713,12 +1746,12 @@ pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
-	PgStat_TableStatus *tabentry;
+	PgStat_IndexStatus *indentry;
 
-	if ((tabentry = find_tabstat_entry(relid)) == NULL)
+	if ((indentry = find_indstat_entry(relid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (tabentry->t_counts.t_blocks_fetched);
+		result = (int64) (indentry->i_counts.i_blocks_fetched);
 
 	PG_RETURN_INT64(result);
 }
@@ -1728,12 +1761,12 @@ pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS)
 {
 	Oid			relid = PG_GETARG_OID(0);
 	int64		result;
-	PgStat_TableStatus *tabentry;
+	PgStat_IndexStatus *indentry;
 
-	if ((tabentry = find_tabstat_entry(relid)) == NULL)
+	if ((indentry = find_indstat_entry(relid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (tabentry->t_counts.t_blocks_hit);
+		result = (int64) (indentry->i_counts.i_blocks_hit);
 
 	PG_RETURN_INT64(result);
 }
@@ -1852,7 +1885,8 @@ pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
 {
 	Oid			taboid = PG_GETARG_OID(0);
 
-	pgstat_reset(PGSTAT_KIND_RELATION, MyDatabaseId, taboid);
+	pgstat_reset(PGSTAT_KIND_TABLE, MyDatabaseId, taboid);
+	pgstat_reset(PGSTAT_KIND_INDEX, MyDatabaseId, taboid);
 
 	PG_RETURN_VOID();
 }
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index a50eecc7c8..e74704742c 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -2411,7 +2411,10 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc)
 	RelationCloseSmgr(relation);
 
 	/* break mutual link with stats entry */
-	pgstat_unlink_relation(relation);
+	if (relation->rd_rel->relkind == RELKIND_INDEX)
+		pgstat_unlink_index(relation);
+	else
+		pgstat_unlink_table(relation);
 
 	/*
 	 * Free all the subsidiary data structures of the relcache entry, then the
@@ -2727,8 +2730,9 @@ RelationClearRelation(Relation relation, bool rebuild)
 			SWAPFIELD(RowSecurityDesc *, rd_rsdesc);
 		/* toast OID override must be preserved */
 		SWAPFIELD(Oid, rd_toastoid);
-		/* pgstat_info / enabled must be preserved */
-		SWAPFIELD(struct PgStat_TableStatus *, pgstat_info);
+		/* pgstattab_info / pgstatind_info / enabled must be preserved */
+		SWAPFIELD(struct PgStat_TableStatus *, pgstattab_info);
+		SWAPFIELD(struct PgStat_IndexStatus *, pgstatind_info);
 		SWAPFIELD(bool, pgstat_enabled);
 		/* preserve old partition key if we have one */
 		if (keep_partkey)
@@ -6321,7 +6325,8 @@ load_relcache_init_file(bool shared)
 		rel->rd_firstRelfilelocatorSubid = InvalidSubTransactionId;
 		rel->rd_droppedSubid = InvalidSubTransactionId;
 		rel->rd_amcache = NULL;
-		rel->pgstat_info = NULL;
+		rel->pgstattab_info = NULL;
+		rel->pgstatind_info = NULL;
 
 		/*
 		 * Recompute lock and physical addressing info.  This is needed in
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f9301b2627..c3fe4af669 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5274,96 +5274,120 @@
   proargnames => '{mcv_list,index,values,nulls,frequency,base_frequency}',
   prosrc => 'pg_stats_ext_mcvlist_items' },
 
-{ oid => '1928', descr => 'statistics: number of scans done for table/index',
-  proname => 'pg_stat_get_numscans', provolatile => 's', proparallel => 'r',
+{ oid => '1928', descr => 'statistics: number of scans done for table',
+  proname => 'pg_stat_get_tab_numscans', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_numscans' },
-{ oid => '9976', descr => 'statistics: time of the last scan for table/index',
-  proname => 'pg_stat_get_lastscan', provolatile => 's', proparallel => 'r',
+  prosrc => 'pg_stat_get_tab_numscans' },
+{ oid => '8296', descr => 'statistics: number of scans done for index',
+  proname => 'pg_stat_get_ind_numscans', provolatile => 's', proparallel => 'r',
+  prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_ind_numscans' },
+{ oid => '9976', descr => 'statistics: time of the last scan for table',
+  proname => 'pg_stat_get_tab_lastscan', provolatile => 's', proparallel => 'r',
+  prorettype => 'timestamptz', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_tab_lastscan' },
+{ oid => '8626', descr => 'statistics: time of the last scan for index',
+  proname => 'pg_stat_get_ind_lastscan', provolatile => 's', proparallel => 'r',
   prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_lastscan' },
+  prosrc => 'pg_stat_get_ind_lastscan' },
 { oid => '1929', descr => 'statistics: number of tuples read by seqscan',
-  proname => 'pg_stat_get_tuples_returned', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_returned', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_returned' },
+  prosrc => 'pg_stat_get_tab_tuples_returned' },
+{ oid => '9603', descr => 'statistics: number of tuples read by seqscan',
+  proname => 'pg_stat_get_ind_tuples_returned', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_ind_tuples_returned' },
 { oid => '1930', descr => 'statistics: number of tuples fetched by idxscan',
-  proname => 'pg_stat_get_tuples_fetched', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_fetched', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_tab_tuples_fetched' },
+{ oid => '8526', descr => 'statistics: number of tuples fetched by idxscan',
+  proname => 'pg_stat_get_ind_tuples_fetched', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_fetched' },
+  prosrc => 'pg_stat_get_ind_tuples_fetched' },
 { oid => '1931', descr => 'statistics: number of tuples inserted',
-  proname => 'pg_stat_get_tuples_inserted', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_inserted', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_inserted' },
+  prosrc => 'pg_stat_get_tab_tuples_inserted' },
 { oid => '1932', descr => 'statistics: number of tuples updated',
-  proname => 'pg_stat_get_tuples_updated', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_updated', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_updated' },
+  prosrc => 'pg_stat_get_tab_tuples_updated' },
 { oid => '1933', descr => 'statistics: number of tuples deleted',
-  proname => 'pg_stat_get_tuples_deleted', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_deleted', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_deleted' },
+  prosrc => 'pg_stat_get_tab_tuples_deleted' },
 { oid => '1972', descr => 'statistics: number of tuples hot updated',
-  proname => 'pg_stat_get_tuples_hot_updated', provolatile => 's',
+  proname => 'pg_stat_get_tab_tuples_hot_updated', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_tuples_hot_updated' },
+  prosrc => 'pg_stat_get_tab_tuples_hot_updated' },
 { oid => '2878', descr => 'statistics: number of live tuples',
-  proname => 'pg_stat_get_live_tuples', provolatile => 's', proparallel => 'r',
+  proname => 'pg_stat_get_tab_live_tuples', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_live_tuples' },
+  prosrc => 'pg_stat_get_tab_live_tuples' },
 { oid => '2879', descr => 'statistics: number of dead tuples',
-  proname => 'pg_stat_get_dead_tuples', provolatile => 's', proparallel => 'r',
+  proname => 'pg_stat_get_tab_dead_tuples', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_dead_tuples' },
+  prosrc => 'pg_stat_get_tab_dead_tuples' },
 { oid => '3177',
   descr => 'statistics: number of tuples changed since last analyze',
-  proname => 'pg_stat_get_mod_since_analyze', provolatile => 's',
+  proname => 'pg_stat_get_tab_mod_since_analyze', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_mod_since_analyze' },
+  prosrc => 'pg_stat_get_tab_mod_since_analyze' },
 { oid => '5053',
   descr => 'statistics: number of tuples inserted since last vacuum',
-  proname => 'pg_stat_get_ins_since_vacuum', provolatile => 's',
+  proname => 'pg_stat_get_tab_ins_since_vacuum', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_ins_since_vacuum' },
+  prosrc => 'pg_stat_get_tab_ins_since_vacuum' },
 { oid => '1934', descr => 'statistics: number of blocks fetched',
-  proname => 'pg_stat_get_blocks_fetched', provolatile => 's',
+  proname => 'pg_stat_get_tab_blocks_fetched', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_blocks_fetched' },
+  prosrc => 'pg_stat_get_tab_blocks_fetched' },
+{ oid => '9432', descr => 'statistics: number of blocks fetched',
+  proname => 'pg_stat_get_ind_blocks_fetched', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_ind_blocks_fetched' },
 { oid => '1935', descr => 'statistics: number of blocks found in cache',
-  proname => 'pg_stat_get_blocks_hit', provolatile => 's', proparallel => 'r',
+  proname => 'pg_stat_get_tab_blocks_hit', provolatile => 's', proparallel => 'r',
+  prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_tab_blocks_hit' },
+{ oid => '8354', descr => 'statistics: number of blocks found in cache',
+  proname => 'pg_stat_get_ind_blocks_hit', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_blocks_hit' },
+  prosrc => 'pg_stat_get_ind_blocks_hit' },
 { oid => '2781', descr => 'statistics: last manual vacuum time for a table',
-  proname => 'pg_stat_get_last_vacuum_time', provolatile => 's',
+  proname => 'pg_stat_get_tab_last_vacuum_time', provolatile => 's',
   proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_last_vacuum_time' },
+  prosrc => 'pg_stat_get_tab_last_vacuum_time' },
 { oid => '2782', descr => 'statistics: last auto vacuum time for a table',
-  proname => 'pg_stat_get_last_autovacuum_time', provolatile => 's',
+  proname => 'pg_stat_get_tab_last_autovacuum_time', provolatile => 's',
   proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_last_autovacuum_time' },
+  prosrc => 'pg_stat_get_tab_last_autovacuum_time' },
 { oid => '2783', descr => 'statistics: last manual analyze time for a table',
-  proname => 'pg_stat_get_last_analyze_time', provolatile => 's',
+  proname => 'pg_stat_get_tab_last_analyze_time', provolatile => 's',
   proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_last_analyze_time' },
+  prosrc => 'pg_stat_get_tab_last_analyze_time' },
 { oid => '2784', descr => 'statistics: last auto analyze time for a table',
-  proname => 'pg_stat_get_last_autoanalyze_time', provolatile => 's',
+  proname => 'pg_stat_get_tab_last_autoanalyze_time', provolatile => 's',
   proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_last_autoanalyze_time' },
+  prosrc => 'pg_stat_get_tab_last_autoanalyze_time' },
 { oid => '3054', descr => 'statistics: number of manual vacuums for a table',
-  proname => 'pg_stat_get_vacuum_count', provolatile => 's', proparallel => 'r',
+  proname => 'pg_stat_get_tab_vacuum_count', provolatile => 's', proparallel => 'r',
   prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_vacuum_count' },
+  prosrc => 'pg_stat_get_tab_vacuum_count' },
 { oid => '3055', descr => 'statistics: number of auto vacuums for a table',
-  proname => 'pg_stat_get_autovacuum_count', provolatile => 's',
+  proname => 'pg_stat_get_tab_autovacuum_count', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_autovacuum_count' },
+  prosrc => 'pg_stat_get_tab_autovacuum_count' },
 { oid => '3056', descr => 'statistics: number of manual analyzes for a table',
-  proname => 'pg_stat_get_analyze_count', provolatile => 's',
+  proname => 'pg_stat_get_tab_analyze_count', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_analyze_count' },
+  prosrc => 'pg_stat_get_tab_analyze_count' },
 { oid => '3057', descr => 'statistics: number of auto analyzes for a table',
-  proname => 'pg_stat_get_autoanalyze_count', provolatile => 's',
+  proname => 'pg_stat_get_tab_autoanalyze_count', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_autoanalyze_count' },
+  prosrc => 'pg_stat_get_tab_autoanalyze_count' },
 { oid => '1936', descr => 'statistics: currently active backend IDs',
   proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
   provolatile => 's', proparallel => 'r', prorettype => 'int4',
@@ -5719,10 +5743,15 @@
   prosrc => 'pg_stat_get_function_self_time' },
 
 { oid => '3037',
-  descr => 'statistics: number of scans done for table/index in current transaction',
-  proname => 'pg_stat_get_xact_numscans', provolatile => 'v',
+  descr => 'statistics: number of scans done for table in current transaction',
+  proname => 'pg_stat_get_tab_xact_numscans', provolatile => 'v',
+  proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_tab_xact_numscans' },
+{ oid => '8892',
+  descr => 'statistics: number of scans done for index in current transaction',
+  proname => 'pg_stat_get_ind_xact_numscans', provolatile => 'v',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
-  prosrc => 'pg_stat_get_xact_numscans' },
+  prosrc => 'pg_stat_get_ind_xact_numscans' },
 { oid => '3038',
   descr => 'statistics: number of tuples read by seqscan in current transaction',
   proname => 'pg_stat_get_xact_tuples_returned', provolatile => 'v',
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index bc6349727b..57f5c8657a 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -39,7 +39,8 @@ typedef enum PgStat_Kind
 
 	/* stats for variable-numbered objects */
 	PGSTAT_KIND_DATABASE,		/* database-wide statistics */
-	PGSTAT_KIND_RELATION,		/* per-table statistics */
+	PGSTAT_KIND_TABLE,			/* per-table statistics */
+	PGSTAT_KIND_INDEX,			/* per-index statistics */
 	PGSTAT_KIND_FUNCTION,		/* per-function statistics */
 	PGSTAT_KIND_REPLSLOT,		/* per-slot statistics */
 	PGSTAT_KIND_SUBSCRIPTION,	/* per-subscription statistics */
@@ -145,6 +146,28 @@ typedef struct PgStat_BackendSubEntry
 	PgStat_Counter sync_error_count;
 } PgStat_BackendSubEntry;
 
+/* ----------
+ * PgStat_IndexCounts			The actual per-index counts kept by a backend
+ *
+ * This struct should contain only actual event counters, because we memcmp
+ * it against zeroes to detect whether there are any stats updates to apply.
+ * It is a component of PgStat_IndexStatus (within-backend state).
+ *
+ * tuples_returned is the number of index entries returned by
+ * the index AM, while tuples_fetched is the number of tuples successfully
+ * fetched by heap_fetch under the control of simple indexscans for this index.
+ * ----------
+ */
+typedef struct PgStat_IndexCounts
+{
+	PgStat_Counter i_numscans;
+
+	PgStat_Counter i_tuples_returned;
+	PgStat_Counter i_tuples_fetched;
+	PgStat_Counter i_blocks_fetched;
+	PgStat_Counter i_blocks_hit;
+} PgStat_IndexCounts;
+
 /* ----------
  * PgStat_TableCounts			The actual per-table counts kept by a backend
  *
@@ -152,12 +175,9 @@ typedef struct PgStat_BackendSubEntry
  * it against zeroes to detect whether there are any stats updates to apply.
  * It is a component of PgStat_TableStatus (within-backend state).
  *
- * Note: for a table, tuples_returned is the number of tuples successfully
+ * Note: tuples_returned is the number of tuples successfully
  * fetched by heap_getnext, while tuples_fetched is the number of tuples
  * successfully fetched by heap_fetch under the control of bitmap indexscans.
- * For an index, tuples_returned is the number of index entries returned by
- * the index AM, while tuples_fetched is the number of tuples successfully
- * fetched by heap_fetch under the control of simple indexscans for this index.
  *
  * tuples_inserted/updated/deleted/hot_updated count attempted actions,
  * regardless of whether the transaction committed.  delta_live_tuples,
@@ -210,6 +230,22 @@ typedef struct PgStat_TableStatus
 	Relation	relation;		/* rel that is using this entry */
 } PgStat_TableStatus;
 
+/* ----------
+ * PgStat_IndexStatus			Per-index status within a backend
+ *
+ * Many of the event counters are nontransactional, ie, we count events
+ * in committed and aborted transactions alike.  For these, we just count
+ * directly in the PgStat_IndexStatus.
+ * ----------
+ */
+typedef struct PgStat_IndexStatus
+{
+	Oid			r_id;			/* relation's OID */
+	bool		r_shared;		/* is it a shared catalog? */
+	PgStat_IndexCounts i_counts;	/* event counts to be sent */
+	Relation	relation;		/* rel that is using this entry */
+} PgStat_IndexStatus;
+
 /* ----------
  * PgStat_TableXactStatus		Per-table, per-subtransaction status
  * ----------
@@ -382,6 +418,17 @@ typedef struct PgStat_StatTabEntry
 	PgStat_Counter autoanalyze_count;
 } PgStat_StatTabEntry;
 
+typedef struct PgStat_StatIndEntry
+{
+	PgStat_Counter numscans;
+	TimestampTz lastscan;
+
+	PgStat_Counter tuples_returned;
+	PgStat_Counter tuples_fetched;
+	PgStat_Counter blocks_fetched;
+	PgStat_Counter blocks_hit;
+} PgStat_StatIndEntry;
+
 typedef struct PgStat_WalStats
 {
 	PgStat_Counter wal_records;
@@ -494,16 +541,15 @@ extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
 
 
 /*
- * Functions in pgstat_relation.c
+ * Functions in pgstat_table.c
  */
 
-extern void pgstat_create_relation(Relation rel);
-extern void pgstat_drop_relation(Relation rel);
-extern void pgstat_copy_relation_stats(Relation dst, Relation src);
+extern void pgstat_create_table(Relation rel);
+extern void pgstat_drop_table(Relation rel);
+extern void pgstat_init_table(Relation rel);
 
-extern void pgstat_init_relation(Relation rel);
-extern void pgstat_assoc_relation(Relation rel);
-extern void pgstat_unlink_relation(Relation rel);
+extern void pgstat_assoc_table(Relation rel);
+extern void pgstat_unlink_table(Relation rel);
 
 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
 								 PgStat_Counter livetuples, PgStat_Counter deadtuples);
@@ -511,53 +557,83 @@ extern void pgstat_report_analyze(Relation rel,
 								  PgStat_Counter livetuples, PgStat_Counter deadtuples,
 								  bool resetcounter);
 
+/*
+ * Functions in pgstat_index.c
+ */
+
+extern void pgstat_create_index(Relation rel);
+extern void pgstat_drop_index(Relation rel);
+extern void pgstat_copy_index_stats(Relation dst, Relation src);
+extern void pgstat_init_index(Relation rel);
+extern void pgstat_assoc_index(Relation rel);
+extern void pgstat_unlink_index(Relation rel);
+
 /*
  * If stats are enabled, but pending data hasn't been prepared yet, call
- * pgstat_assoc_relation() to do so. See its comment for why this is done
- * separately from pgstat_init_relation().
+ * pgstat_assoc_table() / pgstat_assoc_index() to do so.
+ * See their comment for why this is done separately from pgstat_init_table()
+ * and pgstat_init_index().
  */
-#define pgstat_should_count_relation(rel)                           \
-	(likely((rel)->pgstat_info != NULL) ? true :                    \
-	 ((rel)->pgstat_enabled ? pgstat_assoc_relation(rel), true : false))
+#define pgstat_should_count_table(rel)                           \
+	(likely((rel)->pgstattab_info != NULL) ? true :                    \
+	 ((rel)->pgstat_enabled ? pgstat_assoc_table(rel), true : false))
+
+#define pgstat_should_count_index(rel)                           \
+	(likely((rel)->pgstatind_info != NULL) ? true :                    \
+	 ((rel)->pgstat_enabled ? pgstat_assoc_index(rel), true : false))
 
 /* nontransactional event counts are simple enough to inline */
 
 #define pgstat_count_heap_scan(rel)									\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_numscans++;				\
+		if (pgstat_should_count_table(rel))						\
+			(rel)->pgstattab_info->t_counts.t_numscans++;				\
 	} while (0)
 #define pgstat_count_heap_getnext(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_tuples_returned++;		\
+		if (pgstat_should_count_table(rel))						\
+			(rel)->pgstattab_info->t_counts.t_tuples_returned++;		\
 	} while (0)
 #define pgstat_count_heap_fetch(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_tuples_fetched++;		\
+		if (pgstat_should_count_table(rel))						\
+			(rel)->pgstattab_info->t_counts.t_tuples_fetched++;		\
+	} while (0)
+#define pgstat_count_index_fetch(rel)								\
+	do {															\
+		if (pgstat_should_count_index(rel))						\
+			(rel)->pgstatind_info->i_counts.i_tuples_fetched++;		\
 	} while (0)
 #define pgstat_count_index_scan(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_numscans++;				\
+		if (pgstat_should_count_index(rel))						\
+			(rel)->pgstatind_info->i_counts.i_numscans++;			\
 	} while (0)
 #define pgstat_count_index_tuples(rel, n)							\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_tuples_returned += (n);	\
+		if (pgstat_should_count_index(rel))						\
+			(rel)->pgstatind_info->i_counts.i_tuples_returned += (n);	\
 	} while (0)
-#define pgstat_count_buffer_read(rel)								\
+#define pgstat_count_table_buffer_read(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_blocks_fetched++;		\
+		if (pgstat_should_count_table(rel))	\
+			(rel)->pgstattab_info->t_counts.t_blocks_fetched++;		\
 	} while (0)
-#define pgstat_count_buffer_hit(rel)								\
+#define pgstat_count_index_buffer_read(rel)								\
 	do {															\
-		if (pgstat_should_count_relation(rel))						\
-			(rel)->pgstat_info->t_counts.t_blocks_hit++;			\
+		if (pgstat_should_count_index(rel))	\
+			(rel)->pgstatind_info->i_counts.i_blocks_fetched++;		\
+	} while (0)
+#define pgstat_count_table_buffer_hit(rel)								\
+	do {															\
+		if (pgstat_should_count_table(rel))	\
+			(rel)->pgstattab_info->t_counts.t_blocks_hit++; \
+	} while (0)
+#define pgstat_count_index_buffer_hit(rel)								\
+	do {															\
+		if (pgstat_should_count_index(rel))	\
+			(rel)->pgstatind_info->i_counts.i_blocks_hit++; \
 	} while (0)
-
 extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n);
 extern void pgstat_count_heap_update(Relation rel, bool hot);
 extern void pgstat_count_heap_delete(Relation rel);
@@ -573,6 +649,10 @@ extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry_ext(bool shared,
 														   Oid reloid);
 extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
+extern PgStat_IndexStatus *find_indstat_entry(Oid rel_id);
+extern PgStat_StatIndEntry *pgstat_fetch_stat_indentry(Oid relid);
+extern PgStat_StatIndEntry *pgstat_fetch_stat_indentry_ext(bool shared,
+														   Oid relid);
 
 
 /*
diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
index e2c7b59324..004e5412ab 100644
--- a/src/include/utils/pgstat_internal.h
+++ b/src/include/utils/pgstat_internal.h
@@ -359,11 +359,17 @@ typedef struct PgStatShared_Database
 	PgStat_StatDBEntry stats;
 } PgStatShared_Database;
 
-typedef struct PgStatShared_Relation
+typedef struct PgStatShared_Table
 {
 	PgStatShared_Common header;
 	PgStat_StatTabEntry stats;
-} PgStatShared_Relation;
+} PgStatShared_Table;
+
+typedef struct PgStatShared_Index
+{
+	PgStatShared_Common header;
+	PgStat_StatIndEntry stats;
+} PgStatShared_Index;
 
 typedef struct PgStatShared_Function
 {
@@ -550,16 +556,23 @@ extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
 
 
 /*
- * Functions in pgstat_relation.c
+ * Functions in pgstat_table.c
  */
 
-extern void AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit);
-extern void AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth);
-extern void AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
-extern void PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
+extern void AtEOXact_PgStat_Tables(PgStat_SubXactStatus *xact_state, bool isCommit);
+extern void AtEOSubXact_PgStat_Tables(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth);
+extern void AtPrepare_PgStat_Tables(PgStat_SubXactStatus *xact_state);
+extern void PostPrepare_PgStat_Tables(PgStat_SubXactStatus *xact_state);
+
+extern bool pgstat_table_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+extern void pgstat_table_delete_pending_cb(PgStat_EntryRef *entry_ref);
+
+/*
+ * Functions in pgstat_index.c
+ */
 
-extern bool pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
-extern void pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref);
+extern bool pgstat_index_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+extern void pgstat_index_delete_pending_cb(PgStat_EntryRef *entry_ref);
 
 
 /*
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index f383a2fca9..796423f3e3 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -248,7 +248,10 @@ typedef struct RelationData
 
 	bool		pgstat_enabled; /* should relation stats be counted */
 	/* use "struct" here to avoid needing to include pgstat.h: */
-	struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
+	/* table's statistics collection area */
+	struct PgStat_TableStatus *pgstattab_info;
+	/* Index's statistics collection area */
+	struct PgStat_IndexStatus *pgstatind_info;
 } RelationData;
 
 
diff --git a/src/test/isolation/expected/stats.out b/src/test/isolation/expected/stats.out
index 61b5a710ec..494adee88b 100644
--- a/src/test/isolation/expected/stats.out
+++ b/src/test/isolation/expected/stats.out
@@ -2166,14 +2166,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2210,14 +2210,14 @@ step s2_table_update_k1: UPDATE test_stat_tab SET value = value + 1 WHERE key =
 step s1_table_drop: DROP TABLE test_stat_tab;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2236,14 +2236,14 @@ pg_stat_force_next_flush
 step s1_track_counts_off: SET track_counts = off;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2275,14 +2275,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2314,14 +2314,14 @@ pg_stat_force_next_flush
 step s1_track_counts_off: SET track_counts = off;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2369,14 +2369,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2401,14 +2401,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2463,14 +2463,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2495,14 +2495,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2558,14 +2558,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2627,14 +2627,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2688,14 +2688,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2755,14 +2755,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2795,14 +2795,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2841,14 +2841,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2881,14 +2881,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2927,14 +2927,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2968,14 +2968,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -3015,14 +3015,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
diff --git a/src/test/isolation/expected/stats_1.out b/src/test/isolation/expected/stats_1.out
index 3854320106..7981747732 100644
--- a/src/test/isolation/expected/stats_1.out
+++ b/src/test/isolation/expected/stats_1.out
@@ -2174,14 +2174,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2218,14 +2218,14 @@ step s2_table_update_k1: UPDATE test_stat_tab SET value = value + 1 WHERE key =
 step s1_table_drop: DROP TABLE test_stat_tab;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2244,14 +2244,14 @@ pg_stat_force_next_flush
 step s1_track_counts_off: SET track_counts = off;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2283,14 +2283,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2322,14 +2322,14 @@ pg_stat_force_next_flush
 step s1_track_counts_off: SET track_counts = off;
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2377,14 +2377,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2409,14 +2409,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2471,14 +2471,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2503,14 +2503,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2566,14 +2566,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2635,14 +2635,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2698,14 +2698,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2767,14 +2767,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2809,14 +2809,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2857,14 +2857,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2899,14 +2899,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2947,14 +2947,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -2990,14 +2990,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
@@ -3039,14 +3039,14 @@ pg_stat_force_next_flush
 
 step s1_table_stats: 
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
         pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 
diff --git a/src/test/isolation/specs/stats.spec b/src/test/isolation/specs/stats.spec
index 5b922d788c..53d78f7db1 100644
--- a/src/test/isolation/specs/stats.spec
+++ b/src/test/isolation/specs/stats.spec
@@ -93,14 +93,14 @@ step s1_table_drop { DROP TABLE test_stat_tab; }
 
 step s1_table_stats {
     SELECT
-        pg_stat_get_numscans(tso.oid) AS seq_scan,
-        pg_stat_get_tuples_returned(tso.oid) AS seq_tup_read,
-        pg_stat_get_tuples_inserted(tso.oid) AS n_tup_ins,
-        pg_stat_get_tuples_updated(tso.oid) AS n_tup_upd,
-        pg_stat_get_tuples_deleted(tso.oid) AS n_tup_del,
-        pg_stat_get_live_tuples(tso.oid) AS n_live_tup,
-        pg_stat_get_dead_tuples(tso.oid) AS n_dead_tup,
-        pg_stat_get_vacuum_count(tso.oid) AS vacuum_count
+        pg_stat_get_tab_numscans(tso.oid) AS seq_scan,
+        pg_stat_get_tab_tuples_returned(tso.oid) AS seq_tup_read,
+        pg_stat_get_tab_tuples_inserted(tso.oid) AS n_tup_ins,
+        pg_stat_get_tab_tuples_updated(tso.oid) AS n_tup_upd,
+        pg_stat_get_tab_tuples_deleted(tso.oid) AS n_tup_del,
+        pg_stat_get_tab_live_tuples(tso.oid) AS n_live_tup,
+        pg_stat_get_tab_dead_tuples(tso.oid) AS n_dead_tup,
+        pg_stat_get_tab_vacuum_count(tso.oid) AS vacuum_count
     FROM test_stat_oid AS tso
     WHERE tso.name = 'test_stat_tab'
 }
diff --git a/src/test/recovery/t/029_stats_restart.pl b/src/test/recovery/t/029_stats_restart.pl
index 1bf7b568cc..c25634d33f 100644
--- a/src/test/recovery/t/029_stats_restart.pl
+++ b/src/test/recovery/t/029_stats_restart.pl
@@ -43,8 +43,8 @@ my $sect = "initial";
 is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist");
 is(have_stats('function', $dboid, $funcoid),
 	't', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
-	't', "$sect: relation stats do exist");
+is(have_stats('table', $dboid, $tableoid),
+	't', "$sect: table stats do exist");
 
 # regular shutdown
 $node->stop();
@@ -67,8 +67,8 @@ $sect = "copy";
 is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist");
 is(have_stats('function', $dboid, $funcoid),
 	't', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
-	't', "$sect: relation stats do exist");
+is(have_stats('table', $dboid, $tableoid),
+	't', "$sect: table stats do exist");
 
 $node->stop('immediate');
 
@@ -84,8 +84,8 @@ $sect = "post immediate";
 is(have_stats('database', $dboid, 0), 'f', "$sect: db stats do not exist");
 is(have_stats('function', $dboid, $funcoid),
 	'f', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
-	'f', "$sect: relation stats do not exist");
+is(have_stats('table', $dboid, $tableoid),
+	'f', "$sect: table stats do not exist");
 
 # get rid of backup statsfile
 unlink $statsfile or die "cannot unlink $statsfile $!";
@@ -98,8 +98,8 @@ $sect = "post immediate, new";
 is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist");
 is(have_stats('function', $dboid, $funcoid),
 	't', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
-	't', "$sect: relation stats do exist");
+is(have_stats('table', $dboid, $tableoid),
+	't', "$sect: table stats do exist");
 
 # regular shutdown
 $node->stop();
@@ -117,8 +117,7 @@ $sect = "invalid_overwrite";
 is(have_stats('database', $dboid, 0), 'f', "$sect: db stats do not exist");
 is(have_stats('function', $dboid, $funcoid),
 	'f', "$sect: function stats do not exist");
-is(have_stats('relation', $dboid, $tableoid),
-	'f', "$sect: relation stats do not exist");
+is(have_stats('table', $dboid, $tableoid), 'f', "$sect: table do not exist");
 
 
 ## check invalid stats file starting with valid contents, but followed by
@@ -133,8 +132,8 @@ $sect = "invalid_append";
 is(have_stats('database', $dboid, 0), 'f', "$sect: db stats do not exist");
 is(have_stats('function', $dboid, $funcoid),
 	'f', "$sect: function stats do not exist");
-is(have_stats('relation', $dboid, $tableoid),
-	'f', "$sect: relation stats do not exist");
+is(have_stats('table', $dboid, $tableoid),
+	'f', "$sect: table stats do not exist");
 
 
 ## checks related to stats persistency around restarts and resets
diff --git a/src/test/recovery/t/030_stats_cleanup_replica.pl b/src/test/recovery/t/030_stats_cleanup_replica.pl
index cc92ddbb52..1e78b13cf9 100644
--- a/src/test/recovery/t/030_stats_cleanup_replica.pl
+++ b/src/test/recovery/t/030_stats_cleanup_replica.pl
@@ -185,7 +185,7 @@ sub test_standby_func_tab_stats_status
 	my %stats;
 
 	$stats{rel} = $node_standby->safe_psql($connect_db,
-		"SELECT pg_stat_have_stats('relation', $dboid, $tableoid)");
+		"SELECT pg_stat_have_stats('table', $dboid, $tableoid)");
 	$stats{func} = $node_standby->safe_psql($connect_db,
 		"SELECT pg_stat_have_stats('function', $dboid, $funcoid)");
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 532ea36990..c2b9f41bf2 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1767,10 +1767,10 @@ pg_stat_all_indexes| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
     i.relname AS indexrelname,
-    pg_stat_get_numscans(i.oid) AS idx_scan,
-    pg_stat_get_lastscan(i.oid) AS last_idx_scan,
-    pg_stat_get_tuples_returned(i.oid) AS idx_tup_read,
-    pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch
+    pg_stat_get_ind_numscans(i.oid) AS idx_scan,
+    pg_stat_get_ind_lastscan(i.oid) AS last_idx_scan,
+    pg_stat_get_ind_tuples_returned(i.oid) AS idx_tup_read,
+    pg_stat_get_ind_tuples_fetched(i.oid) AS idx_tup_fetch
    FROM (((pg_class c
      JOIN pg_index x ON ((c.oid = x.indrelid)))
      JOIN pg_class i ON ((i.oid = x.indexrelid)))
@@ -1779,28 +1779,28 @@ pg_stat_all_indexes| SELECT c.oid AS relid,
 pg_stat_all_tables| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
-    pg_stat_get_numscans(c.oid) AS seq_scan,
-    pg_stat_get_lastscan(c.oid) AS last_seq_scan,
-    pg_stat_get_tuples_returned(c.oid) AS seq_tup_read,
-    (sum(pg_stat_get_numscans(i.indexrelid)))::bigint AS idx_scan,
-    max(pg_stat_get_lastscan(i.indexrelid)) AS last_idx_scan,
-    ((sum(pg_stat_get_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_tuples_fetched(c.oid)) AS idx_tup_fetch,
-    pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins,
-    pg_stat_get_tuples_updated(c.oid) AS n_tup_upd,
-    pg_stat_get_tuples_deleted(c.oid) AS n_tup_del,
-    pg_stat_get_tuples_hot_updated(c.oid) AS n_tup_hot_upd,
-    pg_stat_get_live_tuples(c.oid) AS n_live_tup,
-    pg_stat_get_dead_tuples(c.oid) AS n_dead_tup,
-    pg_stat_get_mod_since_analyze(c.oid) AS n_mod_since_analyze,
-    pg_stat_get_ins_since_vacuum(c.oid) AS n_ins_since_vacuum,
-    pg_stat_get_last_vacuum_time(c.oid) AS last_vacuum,
-    pg_stat_get_last_autovacuum_time(c.oid) AS last_autovacuum,
-    pg_stat_get_last_analyze_time(c.oid) AS last_analyze,
-    pg_stat_get_last_autoanalyze_time(c.oid) AS last_autoanalyze,
-    pg_stat_get_vacuum_count(c.oid) AS vacuum_count,
-    pg_stat_get_autovacuum_count(c.oid) AS autovacuum_count,
-    pg_stat_get_analyze_count(c.oid) AS analyze_count,
-    pg_stat_get_autoanalyze_count(c.oid) AS autoanalyze_count
+    pg_stat_get_tab_numscans(c.oid) AS seq_scan,
+    pg_stat_get_tab_lastscan(c.oid) AS last_seq_scan,
+    pg_stat_get_tab_tuples_returned(c.oid) AS seq_tup_read,
+    (sum(pg_stat_get_ind_numscans(i.indexrelid)))::bigint AS idx_scan,
+    max(pg_stat_get_ind_lastscan(i.indexrelid)) AS last_idx_scan,
+    ((sum(pg_stat_get_ind_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_tab_tuples_fetched(c.oid)) AS idx_tup_fetch,
+    pg_stat_get_tab_tuples_inserted(c.oid) AS n_tup_ins,
+    pg_stat_get_tab_tuples_updated(c.oid) AS n_tup_upd,
+    pg_stat_get_tab_tuples_deleted(c.oid) AS n_tup_del,
+    pg_stat_get_tab_tuples_hot_updated(c.oid) AS n_tup_hot_upd,
+    pg_stat_get_tab_live_tuples(c.oid) AS n_live_tup,
+    pg_stat_get_tab_dead_tuples(c.oid) AS n_dead_tup,
+    pg_stat_get_tab_mod_since_analyze(c.oid) AS n_mod_since_analyze,
+    pg_stat_get_tab_ins_since_vacuum(c.oid) AS n_ins_since_vacuum,
+    pg_stat_get_tab_last_vacuum_time(c.oid) AS last_vacuum,
+    pg_stat_get_tab_last_autovacuum_time(c.oid) AS last_autovacuum,
+    pg_stat_get_tab_last_analyze_time(c.oid) AS last_analyze,
+    pg_stat_get_tab_last_autoanalyze_time(c.oid) AS last_autoanalyze,
+    pg_stat_get_tab_vacuum_count(c.oid) AS vacuum_count,
+    pg_stat_get_tab_autovacuum_count(c.oid) AS autovacuum_count,
+    pg_stat_get_tab_analyze_count(c.oid) AS analyze_count,
+    pg_stat_get_tab_autoanalyze_count(c.oid) AS autoanalyze_count
    FROM ((pg_class c
      LEFT JOIN pg_index i ON ((c.oid = i.indrelid)))
      LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
@@ -2224,9 +2224,9 @@ pg_stat_wal_receiver| SELECT s.pid,
 pg_stat_xact_all_tables| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
-    pg_stat_get_xact_numscans(c.oid) AS seq_scan,
+    pg_stat_get_tab_xact_numscans(c.oid) AS seq_scan,
     pg_stat_get_xact_tuples_returned(c.oid) AS seq_tup_read,
-    (sum(pg_stat_get_xact_numscans(i.indexrelid)))::bigint AS idx_scan,
+    (sum(pg_stat_get_ind_xact_numscans(i.indexrelid)))::bigint AS idx_scan,
     ((sum(pg_stat_get_xact_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_xact_tuples_fetched(c.oid)) AS idx_tup_fetch,
     pg_stat_get_xact_tuples_inserted(c.oid) AS n_tup_ins,
     pg_stat_get_xact_tuples_updated(c.oid) AS n_tup_upd,
@@ -2277,8 +2277,8 @@ pg_statio_all_indexes| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
     i.relname AS indexrelname,
-    (pg_stat_get_blocks_fetched(i.oid) - pg_stat_get_blocks_hit(i.oid)) AS idx_blks_read,
-    pg_stat_get_blocks_hit(i.oid) AS idx_blks_hit
+    (pg_stat_get_ind_blocks_fetched(i.oid) - pg_stat_get_ind_blocks_hit(i.oid)) AS idx_blks_read,
+    pg_stat_get_ind_blocks_hit(i.oid) AS idx_blks_hit
    FROM (((pg_class c
      JOIN pg_index x ON ((c.oid = x.indrelid)))
      JOIN pg_class i ON ((i.oid = x.indexrelid)))
@@ -2287,31 +2287,31 @@ pg_statio_all_indexes| SELECT c.oid AS relid,
 pg_statio_all_sequences| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
-    (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS blks_read,
-    pg_stat_get_blocks_hit(c.oid) AS blks_hit
+    (pg_stat_get_ind_blocks_fetched(c.oid) - pg_stat_get_tab_blocks_hit(c.oid)) AS blks_read,
+    pg_stat_get_tab_blocks_hit(c.oid) AS blks_hit
    FROM (pg_class c
      LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
   WHERE (c.relkind = 'S'::"char");
 pg_statio_all_tables| SELECT c.oid AS relid,
     n.nspname AS schemaname,
     c.relname,
-    (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS heap_blks_read,
-    pg_stat_get_blocks_hit(c.oid) AS heap_blks_hit,
+    (pg_stat_get_tab_blocks_fetched(c.oid) - pg_stat_get_tab_blocks_hit(c.oid)) AS heap_blks_read,
+    pg_stat_get_tab_blocks_hit(c.oid) AS heap_blks_hit,
     i.idx_blks_read,
     i.idx_blks_hit,
-    (pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid)) AS toast_blks_read,
-    pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit,
+    (pg_stat_get_tab_blocks_fetched(t.oid) - pg_stat_get_tab_blocks_hit(t.oid)) AS toast_blks_read,
+    pg_stat_get_tab_blocks_hit(t.oid) AS toast_blks_hit,
     x.idx_blks_read AS tidx_blks_read,
     x.idx_blks_hit AS tidx_blks_hit
    FROM ((((pg_class c
      LEFT JOIN pg_class t ON ((c.reltoastrelid = t.oid)))
      LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
-     LEFT JOIN LATERAL ( SELECT (sum((pg_stat_get_blocks_fetched(pg_index.indexrelid) - pg_stat_get_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
-            (sum(pg_stat_get_blocks_hit(pg_index.indexrelid)))::bigint AS idx_blks_hit
+     LEFT JOIN LATERAL ( SELECT (sum((pg_stat_get_ind_blocks_fetched(pg_index.indexrelid) - pg_stat_get_ind_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
+            (sum(pg_stat_get_ind_blocks_hit(pg_index.indexrelid)))::bigint AS idx_blks_hit
            FROM pg_index
           WHERE (pg_index.indrelid = c.oid)) i ON (true))
-     LEFT JOIN LATERAL ( SELECT (sum((pg_stat_get_blocks_fetched(pg_index.indexrelid) - pg_stat_get_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
-            (sum(pg_stat_get_blocks_hit(pg_index.indexrelid)))::bigint AS idx_blks_hit
+     LEFT JOIN LATERAL ( SELECT (sum((pg_stat_get_ind_blocks_fetched(pg_index.indexrelid) - pg_stat_get_ind_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
+            (sum(pg_stat_get_ind_blocks_hit(pg_index.indexrelid)))::bigint AS idx_blks_hit
            FROM pg_index
           WHERE (pg_index.indrelid = t.oid)) x ON (true))
   WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]));
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 1d84407a03..d5ee0f4845 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -151,6 +151,117 @@ FROM prevstats AS pr;
 
 COMMIT;
 ----
+-- Basic tests for toast
+---
+CREATE TABLE stats_toast(stuff text);
+ALTER TABLE stats_toast ALTER COLUMN stuff SET STORAGE EXTERNAL;
+INSERT INTO stats_toast VALUES (repeat('a',1000000));
+SELECT count(*) FROM stats_toast WHERE stuff like '%a%';
+ count 
+-------
+     1
+(1 row)
+
+-- ensure pending stats are flushed
+SELECT pg_stat_force_next_flush();
+ pg_stat_force_next_flush 
+--------------------------
+ 
+(1 row)
+
+select toast_blks_read > 0 as toast_blks_read, toast_blks_hit > 0 as toast_blks_hit,
+       tidx_blks_read > 0 as tidx_blks_read, tidx_blks_hit > 0 as tidx_blks_hit,
+       toast_blks_hit >= toast_blks_read,
+       tidx_blks_hit >= tidx_blks_read
+   from pg_statio_all_tables
+ where relname = 'stats_toast';
+ toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit | ?column? | ?column? 
+-----------------+----------------+----------------+---------------+----------+----------
+ t               | t              | t              | t             | t        | t
+(1 row)
+
+----
+-- Basic tests for partition
+---
+CREATE TABLE stats_partition (
+    id1         int not null,
+    id2         int not null
+) PARTITION BY RANGE (id2);
+CREATE TABLE stats_partition_5 PARTITION OF stats_partition
+    FOR VALUES FROM (0) TO (5);
+CREATE TABLE stats_partition_20000 PARTITION OF stats_partition
+    FOR VALUES FROM (5) TO (20001);
+CREATE INDEX ON stats_partition (id2);
+insert into stats_partition select a,a from generate_series(0,20000) a;
+SET enable_seqscan TO off;
+SET enable_bitmapscan TO off;
+select * from stats_partition where id2 = 2000;
+ id1  | id2  
+------+------
+ 2000 | 2000
+(1 row)
+
+select * from stats_partition where id2 = 2;
+ id1 | id2 
+-----+-----
+   2 |   2
+(1 row)
+
+-- ensure pending stats are flushed
+SELECT pg_stat_force_next_flush();
+ pg_stat_force_next_flush 
+--------------------------
+ 
+(1 row)
+
+select relname, indexrelname, idx_scan > 0 as idx_scan, idx_tup_read > 0 as idx_tup_read,
+       idx_tup_fetch > 0 as idx_tup_fetch
+   from pg_stat_all_indexes
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+        relname        |         indexrelname          | idx_scan | idx_tup_read | idx_tup_fetch 
+-----------------------+-------------------------------+----------+--------------+---------------
+ stats_partition_20000 | stats_partition_20000_id2_idx | t        | t            | t
+ stats_partition_5     | stats_partition_5_id2_idx     | t        | t            | t
+(2 rows)
+
+select relname, indexrelname, idx_blks_read > 0 as idx_blks_read,
+       idx_blks_hit > 0 as idx_blks_hit
+   from pg_statio_all_indexes
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+        relname        |         indexrelname          | idx_blks_read | idx_blks_hit 
+-----------------------+-------------------------------+---------------+--------------
+ stats_partition_20000 | stats_partition_20000_id2_idx | t             | t
+ stats_partition_5     | stats_partition_5_id2_idx     | t             | t
+(2 rows)
+
+select relname,seq_scan > 0 as seq_scan, seq_tup_read > 0 as seq_tup_read,
+       idx_scan > 0 as idx_scan, idx_tup_fetch > 0 as idx_tup_fetch
+   from pg_stat_all_tables
+  where relname like '%stats_partition%'
+  order by relname COLLATE "C";
+        relname        | seq_scan | seq_tup_read | idx_scan | idx_tup_fetch 
+-----------------------+----------+--------------+----------+---------------
+ stats_partition       | f        | f            | f        | f
+ stats_partition_20000 | t        | f            | t        | t
+ stats_partition_5     | t        | f            | t        | t
+(3 rows)
+
+select relname, heap_blks_read > 0 as heap_blks_read, heap_blks_hit > 0 as heap_blks_hit,
+       idx_blks_read > 0 as idx_blks_read, idx_blks_hit > 0 as idx_blks_hit
+   from pg_statio_all_tables
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+        relname        | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit 
+-----------------------+----------------+---------------+---------------+--------------
+ stats_partition_20000 | t              | t             | t             | t
+ stats_partition_5     | t              | t             | t             | t
+(2 rows)
+
+SET enable_seqscan TO on;
+SET enable_bitmapscan TO on;
+----
 -- Basic tests for track_functions
 ---
 CREATE FUNCTION stats_test_func1() RETURNS VOID LANGUAGE plpgsql AS $$BEGIN END;$$;
@@ -357,17 +468,17 @@ SELECT pg_stat_force_next_flush();
  
 (1 row)
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           1
 (1 row)
 
 DROP TABLE drop_stats_test;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       0
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           0
 (1 row)
 
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid);
@@ -378,18 +489,18 @@ SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid);
 
 -- check that rollback protects against having stats dropped and that local
 -- modifications don't pose a problem
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
-(1 row)
-
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
- pg_stat_get_tuples_inserted 
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_live_tuples 
 -----------------------------
                            1
 (1 row)
 
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_tuples_inserted 
+---------------------------------
+                               1
+(1 row)
+
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
  pg_stat_get_xact_tuples_inserted 
 ----------------------------------
@@ -418,29 +529,29 @@ SELECT pg_stat_force_next_flush();
  
 (1 row)
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           1
 (1 row)
 
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
- pg_stat_get_tuples_inserted 
------------------------------
-                           2
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_tuples_inserted 
+---------------------------------
+                               2
 (1 row)
 
 -- transactional drop
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           1
 (1 row)
 
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
- pg_stat_get_tuples_inserted 
------------------------------
-                           2
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_tuples_inserted 
+---------------------------------
+                               2
 (1 row)
 
 BEGIN;
@@ -465,23 +576,23 @@ SELECT pg_stat_force_next_flush();
  
 (1 row)
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       0
-(1 row)
-
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
- pg_stat_get_tuples_inserted 
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_live_tuples 
 -----------------------------
                            0
 (1 row)
 
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
+ pg_stat_get_tab_tuples_inserted 
+---------------------------------
+                               0
+(1 row)
+
 -- savepoint rollback (2 levels)
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       1
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           1
 (1 row)
 
 BEGIN;
@@ -510,17 +621,17 @@ SELECT pg_stat_force_next_flush();
  
 (1 row)
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       3
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           3
 (1 row)
 
 -- savepoint rolback (1 level)
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       3
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           3
 (1 row)
 
 BEGIN;
@@ -529,17 +640,17 @@ DROP TABLE drop_stats_test_subxact;
 SAVEPOINT sp2;
 ROLLBACK TO SAVEPOINT sp1;
 COMMIT;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       3
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           3
 (1 row)
 
 -- and now actually drop
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       3
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           3
 (1 row)
 
 BEGIN;
@@ -548,10 +659,10 @@ DROP TABLE drop_stats_test_subxact;
 SAVEPOINT sp2;
 RELEASE SAVEPOINT sp1;
 COMMIT;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
- pg_stat_get_live_tuples 
--------------------------
-                       0
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
+ pg_stat_get_tab_live_tuples 
+-----------------------------
+                           0
 (1 row)
 
 DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4;
@@ -1021,21 +1132,21 @@ select a from stats_test_tab1 where a = 3;
  3
 (1 row)
 
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
 (1 row)
 
 -- pg_stat_have_stats returns false for dropped index with stats
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
 (1 row)
 
 DROP index stats_test_idx1;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  f
@@ -1051,14 +1162,14 @@ select a from stats_test_tab1 where a = 3;
  3
 (1 row)
 
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
 (1 row)
 
 ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  f
@@ -1073,7 +1184,7 @@ select a from stats_test_tab1 where a = 3;
  3
 (1 row)
 
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
@@ -1081,7 +1192,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
 
 REINDEX index CONCURRENTLY stats_test_idx1;
 -- false for previous oid
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  f
@@ -1089,7 +1200,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
 
 -- true for new oid
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
@@ -1097,7 +1208,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns true for a rolled back drop index with stats
 BEGIN;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
@@ -1105,7 +1216,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
 
 DROP index stats_test_idx1;
 ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
  pg_stat_have_stats 
 --------------------
  t
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index b4d6753c71..1e9ae74b2a 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -126,6 +126,77 @@ FROM prevstats AS pr;
 
 COMMIT;
 
+----
+-- Basic tests for toast
+---
+CREATE TABLE stats_toast(stuff text);
+ALTER TABLE stats_toast ALTER COLUMN stuff SET STORAGE EXTERNAL;
+INSERT INTO stats_toast VALUES (repeat('a',1000000));
+SELECT count(*) FROM stats_toast WHERE stuff like '%a%';
+
+-- ensure pending stats are flushed
+SELECT pg_stat_force_next_flush();
+
+select toast_blks_read > 0 as toast_blks_read, toast_blks_hit > 0 as toast_blks_hit,
+       tidx_blks_read > 0 as tidx_blks_read, tidx_blks_hit > 0 as tidx_blks_hit,
+       toast_blks_hit >= toast_blks_read,
+       tidx_blks_hit >= tidx_blks_read
+   from pg_statio_all_tables
+ where relname = 'stats_toast';
+
+----
+-- Basic tests for partition
+---
+CREATE TABLE stats_partition (
+    id1         int not null,
+    id2         int not null
+) PARTITION BY RANGE (id2);
+
+CREATE TABLE stats_partition_5 PARTITION OF stats_partition
+    FOR VALUES FROM (0) TO (5);
+
+CREATE TABLE stats_partition_20000 PARTITION OF stats_partition
+    FOR VALUES FROM (5) TO (20001);
+
+CREATE INDEX ON stats_partition (id2);
+
+insert into stats_partition select a,a from generate_series(0,20000) a;
+
+SET enable_seqscan TO off;
+SET enable_bitmapscan TO off;
+
+select * from stats_partition where id2 = 2000;
+select * from stats_partition where id2 = 2;
+-- ensure pending stats are flushed
+SELECT pg_stat_force_next_flush();
+
+select relname, indexrelname, idx_scan > 0 as idx_scan, idx_tup_read > 0 as idx_tup_read,
+       idx_tup_fetch > 0 as idx_tup_fetch
+   from pg_stat_all_indexes
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+
+select relname, indexrelname, idx_blks_read > 0 as idx_blks_read,
+       idx_blks_hit > 0 as idx_blks_hit
+   from pg_statio_all_indexes
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+
+select relname,seq_scan > 0 as seq_scan, seq_tup_read > 0 as seq_tup_read,
+       idx_scan > 0 as idx_scan, idx_tup_fetch > 0 as idx_tup_fetch
+   from pg_stat_all_tables
+  where relname like '%stats_partition%'
+  order by relname COLLATE "C";
+
+select relname, heap_blks_read > 0 as heap_blks_read, heap_blks_hit > 0 as heap_blks_hit,
+       idx_blks_read > 0 as idx_blks_read, idx_blks_hit > 0 as idx_blks_hit
+   from pg_statio_all_tables
+ where relname like '%stats_partition%'
+ order by relname COLLATE "C";
+
+SET enable_seqscan TO on;
+SET enable_bitmapscan TO on;
+
 ----
 -- Basic tests for track_functions
 ---
@@ -218,15 +289,15 @@ SELECT 'drop_stats_test_subxact'::regclass::oid AS drop_stats_test_subxact_oid \
 
 SELECT pg_stat_force_next_flush();
 
-SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_oid);
 DROP TABLE drop_stats_test;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_oid);
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_oid);
 
 -- check that rollback protects against having stats dropped and that local
 -- modifications don't pose a problem
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
 BEGIN;
 INSERT INTO drop_stats_test_xact DEFAULT VALUES;
@@ -235,12 +306,12 @@ DROP TABLE drop_stats_test_xact;
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
 ROLLBACK;
 SELECT pg_stat_force_next_flush();
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
 
 -- transactional drop
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
 BEGIN;
 INSERT INTO drop_stats_test_xact DEFAULT VALUES;
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
@@ -248,11 +319,11 @@ DROP TABLE drop_stats_test_xact;
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_xact_oid);
 COMMIT;
 SELECT pg_stat_force_next_flush();
-SELECT pg_stat_get_live_tuples(:drop_stats_test_xact_oid);
-SELECT pg_stat_get_tuples_inserted(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_xact_oid);
+SELECT pg_stat_get_tab_tuples_inserted(:drop_stats_test_xact_oid);
 
 -- savepoint rollback (2 levels)
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 BEGIN;
 INSERT INTO drop_stats_test_subxact DEFAULT VALUES;
 SAVEPOINT sp1;
@@ -264,27 +335,27 @@ ROLLBACK TO SAVEPOINT sp2;
 SELECT pg_stat_get_xact_tuples_inserted(:drop_stats_test_subxact_oid);
 COMMIT;
 SELECT pg_stat_force_next_flush();
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 
 -- savepoint rolback (1 level)
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 BEGIN;
 SAVEPOINT sp1;
 DROP TABLE drop_stats_test_subxact;
 SAVEPOINT sp2;
 ROLLBACK TO SAVEPOINT sp1;
 COMMIT;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 
 -- and now actually drop
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 BEGIN;
 SAVEPOINT sp1;
 DROP TABLE drop_stats_test_subxact;
 SAVEPOINT sp2;
 RELEASE SAVEPOINT sp1;
 COMMIT;
-SELECT pg_stat_get_live_tuples(:drop_stats_test_subxact_oid);
+SELECT pg_stat_get_tab_live_tuples(:drop_stats_test_subxact_oid);
 
 DROP TABLE trunc_stats_test, trunc_stats_test1, trunc_stats_test2, trunc_stats_test3, trunc_stats_test4;
 DROP TABLE prevstats;
@@ -493,40 +564,40 @@ CREATE index stats_test_idx1 on stats_test_tab1(a);
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
 SET enable_seqscan TO off;
 select a from stats_test_tab1 where a = 3;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns false for dropped index with stats
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 DROP index stats_test_idx1;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns false for rolled back index creation
 BEGIN;
 CREATE index stats_test_idx1 on stats_test_tab1(a);
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
 select a from stats_test_tab1 where a = 3;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns true for reindex CONCURRENTLY
 CREATE index stats_test_idx1 on stats_test_tab1(a);
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
 select a from stats_test_tab1 where a = 3;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 REINDEX index CONCURRENTLY stats_test_idx1;
 -- false for previous oid
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 -- true for new oid
 SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- pg_stat_have_stats returns true for a rolled back drop index with stats
 BEGIN;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 DROP index stats_test_idx1;
 ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('index', :dboid, :stats_test_idx1_oid);
 
 -- put enable_seqscan back to on
 SET enable_seqscan TO on;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 58daeca831..f9009263bc 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2008,10 +2008,11 @@ PgStatShared_Common
 PgStatShared_Database
 PgStatShared_Function
 PgStatShared_HashEntry
-PgStatShared_Relation
+PgStatShared_Index
 PgStatShared_ReplSlot
 PgStatShared_SLRU
 PgStatShared_Subscription
+PgStatShared_Table
 PgStatShared_Wal
 PgStat_ArchiverStats
 PgStat_BackendFunctionEntry
@@ -2025,6 +2026,7 @@ PgStat_FetchConsistency
 PgStat_FunctionCallUsage
 PgStat_FunctionCounts
 PgStat_HashKey
+PgStat_IndexStatus
 PgStat_Kind
 PgStat_KindInfo
 PgStat_LocalState


view thread (17+ messages)  latest in thread

reply

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: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: Split index and table statistics into different types of stats
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

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