1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Move index statistics into their own stats kind

This commit splits the relation and index stats data, where the index
data is now moved to a new kind called PGSTAT_KIND_INDEX.  A benefit of
this refactoring is a reduction of the shared memory required for each
index, the new PgStat_StatIdxEntry including only the fields required
for indexes.  This leads to less data flushed to disk on shutdown.
Another benefit is that the addition of new fields for relation-level
stats is easier to think about.  Note that indexes have no need for most
of the xact-level fields that relations care about, clarifying the role
of each counter for each relkind.

System views are updated to use the index-level functions.  Note this
split means a possible break for tools that had the idea to call the
SQL functions for relation stats (not documented), as now these would
return 0 when queried for an index.  These tools can use the new index
functions to achieve the same result.

As of this change, the pending statistics are still controlled by
PgStat_TableStatus for both relation and index kinds.  This is left as a
follow-up piece, this one being good enough on its own.  This commit is
focused on the changes required for the SQL interface, shared memory
management and the on-disk format.

Bump catalog version.
Bump PGSTAT_FILE_FORMAT_ID.

Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Author: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/f572abe7-a1bb-e13b-48c7-2ca150546822@gmail.com
This commit is contained in:
Michael Paquier
2026-08-12 12:06:05 +09:00
parent feb15361b3
commit 72a6dad1c9
17 changed files with 547 additions and 119 deletions

View File

@@ -5877,6 +5877,24 @@ description | Waiting for a newly initialized WAL file to reach durable storage
</para></entry>
</row>
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
<primary>pg_stat_reset_single_index_counters</primary>
</indexterm>
<function>pg_stat_reset_single_index_counters</function> ( <type>oid</type> )
<returnvalue>void</returnvalue>
</para>
<para>
Resets statistics for a single index in the current database
or shared across all databases in the cluster to zero.
</para>
<para>
This function is restricted to superusers by default, but other users
can be granted EXECUTE to run the function.
</para></entry>
</row>
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
@@ -6022,7 +6040,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
<returnvalue>void</returnvalue>
</para>
<para>
Resets statistics for a single table or index in the current database
Resets statistics for a single table in the current database
or shared across all databases in the cluster to zero.
It also resets statistics for a single sequence or materialized view
in the current database.

View File

@@ -722,9 +722,9 @@ CREATE VIEW pg_stat_all_tables AS
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 +
sum(pg_stat_get_idx_numscans(I.indexrelid))::bigint AS idx_scan,
max(pg_stat_get_idx_lastscan(I.indexrelid)) AS last_idx_scan,
sum(pg_stat_get_idx_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,
@@ -761,8 +761,8 @@ CREATE VIEW pg_stat_xact_all_tables AS
C.relname AS relname,
pg_stat_get_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_xact_tuples_fetched(I.indexrelid))::bigint +
sum(pg_stat_get_xact_idx_numscans(I.indexrelid))::bigint AS idx_scan,
sum(pg_stat_get_xact_idx_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,
@@ -833,17 +833,17 @@ CREATE VIEW pg_statio_all_tables AS
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_idx_blocks_fetched(indexrelid) -
pg_stat_get_idx_blocks_hit(indexrelid))::bigint
AS idx_blks_read,
sum(pg_stat_get_blocks_hit(indexrelid))::bigint
sum(pg_stat_get_idx_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_idx_blocks_fetched(indexrelid) -
pg_stat_get_idx_blocks_hit(indexrelid))::bigint
AS idx_blks_read,
sum(pg_stat_get_blocks_hit(indexrelid))::bigint
sum(pg_stat_get_idx_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');
@@ -865,11 +865,11 @@ 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_stat_reset_time(I.oid) AS stats_reset
pg_stat_get_idx_numscans(I.oid) AS idx_scan,
pg_stat_get_idx_lastscan(I.oid) AS last_idx_scan,
pg_stat_get_idx_tuples_returned(I.oid) AS idx_tup_read,
pg_stat_get_idx_tuples_fetched(I.oid) AS idx_tup_fetch,
pg_stat_get_idx_stat_reset_time(I.oid) AS stats_reset
FROM pg_class C JOIN
pg_index X ON C.oid = X.indrelid JOIN
pg_class I ON I.oid = X.indexrelid
@@ -893,10 +893,10 @@ 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_stat_reset_time(I.oid) AS stats_reset
pg_stat_get_idx_blocks_fetched(I.oid) -
pg_stat_get_idx_blocks_hit(I.oid) AS idx_blks_read,
pg_stat_get_idx_blocks_hit(I.oid) AS idx_blks_hit,
pg_stat_get_idx_stat_reset_time(I.oid) AS stats_reset
FROM pg_class C JOIN
pg_index X ON C.oid = X.indrelid JOIN
pg_class I ON I.oid = X.indexrelid

View File

@@ -25,6 +25,7 @@ OBJS = \
pgstat_checkpointer.o \
pgstat_database.o \
pgstat_function.o \
pgstat_index.o \
pgstat_io.o \
pgstat_kind.o \
pgstat_lock.o \

View File

@@ -10,6 +10,7 @@ backend_sources += files(
'pgstat_checkpointer.c',
'pgstat_database.c',
'pgstat_function.c',
'pgstat_index.c',
'pgstat_io.c',
'pgstat_kind.c',
'pgstat_lock.c',

View File

@@ -317,6 +317,22 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
.reset_timestamp_cb = pgstat_relation_reset_timestamp_cb,
},
[PGSTAT_KIND_INDEX] = {
.name = "index",
.fixed_amount = false,
.write_to_file = true,
.shared_size = sizeof(PgStatShared_Index),
.shared_data_off = offsetof(PgStatShared_Index, stats),
.shared_data_len = sizeof(((PgStatShared_Index *) 0)->stats),
.pending_size = sizeof(PgStat_TableStatus),
.flush_pending_cb = pgstat_index_flush_cb,
.delete_pending_cb = pgstat_index_delete_pending_cb,
.reset_timestamp_cb = pgstat_index_reset_timestamp_cb,
},
[PGSTAT_KIND_FUNCTION] = {
.name = "function",

View File

@@ -0,0 +1,131 @@
/* -------------------------------------------------------------------------
*
* pgstat_index.c
* Implementation of index statistics.
*
* This file contains the implementation of index statistics.
*
* Copyright (c) 2001-2026, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/backend/utils/activity/pgstat_index.c
* -------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "utils/memutils.h"
#include "utils/pgstat_internal.h"
#include "utils/rel.h"
#include "utils/timestamp.h"
/*
* Flush out pending stats for an index entry.
*
* If nowait is true and the lock could not be immediately acquired, returns
* false without flushing the entry. Otherwise returns true.
*
* 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)
{
Oid dboid;
PgStat_TableStatus *lstats; /* pending stats entry */
PgStatShared_Index *shidxstats;
PgStat_StatIdxEntry *idxentry; /* index entry of shared stats */
PgStat_StatDBEntry *dbentry; /* pending database entry */
dboid = entry_ref->shared_entry->key.dboid;
lstats = (PgStat_TableStatus *) entry_ref->pending;
shidxstats = (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 (pg_memory_is_all_zeros(&lstats->counts,
sizeof(struct PgStat_TableCounts)))
return true;
if (!pgstat_lock_entry(entry_ref, nowait))
return false;
/* Add the values to the shared entry. */
idxentry = &shidxstats->stats;
idxentry->numscans += lstats->counts.numscans;
if (lstats->counts.numscans)
{
TimestampTz t = GetCurrentTransactionStopTimestamp();
if (t > idxentry->lastscan)
idxentry->lastscan = t;
}
idxentry->tuples_returned += lstats->counts.tuples_returned;
idxentry->tuples_fetched += lstats->counts.tuples_fetched;
idxentry->blocks_fetched += lstats->counts.blocks_fetched;
idxentry->blocks_hit += lstats->counts.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->tuples_returned += lstats->counts.tuples_returned;
dbentry->tuples_fetched += lstats->counts.tuples_fetched;
dbentry->blocks_fetched += lstats->counts.blocks_fetched;
dbentry->blocks_hit += lstats->counts.blocks_hit;
return true;
}
/*
* Callback to delete pending index stats.
*/
void
pgstat_index_delete_pending_cb(PgStat_EntryRef *entry_ref)
{
PgStat_TableStatus *pending = (PgStat_TableStatus *) entry_ref->pending;
if (pending->relation)
pgstat_unlink_relation(pending->relation);
}
/*
* Callback to reset the timestamp on an index stats entry.
*/
void
pgstat_index_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
{
((PgStatShared_Index *) header)->stats.stat_reset_time = ts;
}
/*
* 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_StatIdxEntry *
pgstat_fetch_stat_idxentry(Oid relid)
{
return pgstat_fetch_stat_idxentry_ext(IsSharedRelation(relid), relid, NULL);
}
/*
* More efficient version of pgstat_fetch_stat_idxentry(), allowing to specify
* whether the to-be-accessed index is a shared relation or not. This version
* also returns whether the caller can pfree() the result if desired.
*/
PgStat_StatIdxEntry *
pgstat_fetch_stat_idxentry_ext(bool shared, Oid reloid, bool *may_free)
{
Oid dboid = (shared ? InvalidOid : MyDatabaseId);
return (PgStat_StatIdxEntry *)
pgstat_fetch_entry(PGSTAT_KIND_INDEX, dboid, reloid, may_free);
}

View File

@@ -42,12 +42,24 @@ typedef struct TwoPhasePgStatRecord
} TwoPhasePgStatRecord;
static PgStat_TableStatus *pgstat_prep_relation_pending(Oid rel_id, bool isshared);
static PgStat_TableStatus *pgstat_prep_relation_pending(PgStat_Kind kind,
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 void save_truncdrop_counters(PgStat_TableXactStatus *trans, bool is_drop);
static void restore_truncdrop_counters(PgStat_TableXactStatus *trans);
/*
* Determine the stats kind for a relation based on its relkind.
*/
static inline PgStat_Kind
pgstat_get_relation_kind(char relkind)
{
if (relkind == RELKIND_INDEX)
return PGSTAT_KIND_INDEX;
return PGSTAT_KIND_RELATION;
}
/*
* Copy stats between relations. This is used for things like REINDEX
@@ -56,25 +68,52 @@ static void restore_truncdrop_counters(PgStat_TableXactStatus *trans);
void
pgstat_copy_relation_stats(Relation dst, Relation src)
{
PgStat_StatTabEntry *srcstats;
PgStatShared_Relation *dstshstats;
PgStat_EntryRef *dst_ref;
PgStat_Kind kind = pgstat_get_relation_kind(src->rd_rel->relkind);
srcstats = pgstat_fetch_stat_tabentry_ext(src->rd_rel->relisshared,
RelationGetRelid(src),
NULL);
if (!srcstats)
return;
if (kind == PGSTAT_KIND_INDEX)
{
PgStat_StatIdxEntry *srcstats;
PgStatShared_Index *dstshstats;
PgStat_EntryRef *dst_ref;
dst_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION,
dst->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
RelationGetRelid(dst),
false);
srcstats = pgstat_fetch_stat_idxentry_ext(src->rd_rel->relisshared,
RelationGetRelid(src),
NULL);
if (!srcstats)
return;
dstshstats = (PgStatShared_Relation *) dst_ref->shared_stats;
dstshstats->stats = *srcstats;
dst_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_INDEX,
dst->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
RelationGetRelid(dst),
false);
pgstat_unlock_entry(dst_ref);
dstshstats = (PgStatShared_Index *) dst_ref->shared_stats;
dstshstats->stats = *srcstats;
pgstat_unlock_entry(dst_ref);
}
else
{
PgStat_StatTabEntry *srcstats;
PgStatShared_Relation *dstshstats;
PgStat_EntryRef *dst_ref;
srcstats = pgstat_fetch_stat_tabentry_ext(src->rd_rel->relisshared,
RelationGetRelid(src),
NULL);
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);
}
}
/*
@@ -131,11 +170,16 @@ pgstat_init_relation(Relation rel)
void
pgstat_assoc_relation(Relation rel)
{
PgStat_Kind kind;
Assert(rel->pgstat_enabled);
Assert(rel->pgstat_info == NULL);
kind = pgstat_get_relation_kind(rel->rd_rel->relkind);
/* find or make the PgStat_TableStatus entry, and update link */
rel->pgstat_info = pgstat_prep_relation_pending(RelationGetRelid(rel),
rel->pgstat_info = pgstat_prep_relation_pending(kind,
RelationGetRelid(rel),
rel->rd_rel->relisshared);
/* don't allow link a stats to multiple relcache entries */
@@ -168,7 +212,9 @@ pgstat_unlink_relation(Relation rel)
void
pgstat_create_relation(Relation rel)
{
pgstat_create_transactional(PGSTAT_KIND_RELATION,
PgStat_Kind kind = pgstat_get_relation_kind(rel->rd_rel->relkind);
pgstat_create_transactional(kind,
rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
RelationGetRelid(rel));
}
@@ -181,8 +227,9 @@ pgstat_drop_relation(Relation rel)
{
int nest_level = GetCurrentTransactionNestLevel();
PgStat_TableStatus *pgstat_info;
PgStat_Kind kind = pgstat_get_relation_kind(rel->rd_rel->relkind);
pgstat_drop_transactional(PGSTAT_KIND_RELATION,
pgstat_drop_transactional(kind,
rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
RelationGetRelid(rel));
@@ -500,16 +547,25 @@ pgstat_fetch_stat_tabentry_ext(bool shared, Oid reloid, bool *may_free)
*/
PgStat_TableStatus *
find_tabstat_entry(Oid rel_id)
{
return find_tabstat_entry_kind(PGSTAT_KIND_RELATION, rel_id);
}
/*
* Same as find_tabstat_entry but for a specific stats kind.
*/
PgStat_TableStatus *
find_tabstat_entry_kind(PgStat_Kind kind, Oid rel_id)
{
PgStat_EntryRef *entry_ref;
PgStat_TableXactStatus *trans;
PgStat_TableStatus *tabentry = NULL;
PgStat_TableStatus *tablestatus = NULL;
entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, MyDatabaseId, rel_id);
entry_ref = pgstat_fetch_pending_entry(kind, MyDatabaseId, rel_id);
if (!entry_ref)
{
entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, InvalidOid, rel_id);
entry_ref = pgstat_fetch_pending_entry(kind, InvalidOid, rel_id);
if (!entry_ref)
return tablestatus;
}
@@ -752,7 +808,7 @@ pgstat_twophase_postcommit(FullTransactionId fxid, uint16 info,
PgStat_TableStatus *pgstat_info;
/* Find or create a tabstat entry for the rel */
pgstat_info = pgstat_prep_relation_pending(rec->id, rec->shared);
pgstat_info = pgstat_prep_relation_pending(PGSTAT_KIND_RELATION, rec->id, rec->shared);
/* Same math as in AtEOXact_PgStat, commit case */
pgstat_info->counts.tuples_inserted += rec->tuples_inserted;
@@ -788,7 +844,7 @@ pgstat_twophase_postabort(FullTransactionId fxid, uint16 info,
PgStat_TableStatus *pgstat_info;
/* Find or create a tabstat entry for the rel */
pgstat_info = pgstat_prep_relation_pending(rec->id, rec->shared);
pgstat_info = pgstat_prep_relation_pending(PGSTAT_KIND_RELATION, rec->id, rec->shared);
/* Same math as in AtEOXact_PgStat, abort case */
if (rec->truncdropped)
@@ -826,10 +882,7 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
lstats = (PgStat_TableStatus *) entry_ref->pending;
shtabstats = (PgStatShared_Relation *) 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 (pg_memory_is_all_zeros(&lstats->counts,
sizeof(struct PgStat_TableCounts)))
return true;
@@ -922,12 +975,12 @@ pgstat_relation_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
* initialized if not exists.
*/
static PgStat_TableStatus *
pgstat_prep_relation_pending(Oid rel_id, bool isshared)
pgstat_prep_relation_pending(PgStat_Kind kind, 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(kind,
isshared ? InvalidOid : MyDatabaseId,
rel_id, NULL);
pending = entry_ref->pending;

View File

@@ -108,6 +108,40 @@ PG_STAT_GET_RELENTRY_INT64(tuples_updated)
/* pg_stat_get_vacuum_count */
PG_STAT_GET_RELENTRY_INT64(vacuum_count)
/*
* Accessor macro for index stats entries (PgStat_StatIdxEntry).
*/
#define PG_STAT_GET_IDXENTRY_INT64(stat) \
Datum \
CppConcat(pg_stat_get_idx_,stat)(PG_FUNCTION_ARGS) \
{ \
Oid relid = PG_GETARG_OID(0); \
int64 result; \
PgStat_StatIdxEntry *idxentry; \
\
if ((idxentry = pgstat_fetch_stat_idxentry(relid)) == NULL) \
result = 0; \
else \
result = (int64) (idxentry->stat); \
\
PG_RETURN_INT64(result); \
}
/* pg_stat_get_idx_numscans */
PG_STAT_GET_IDXENTRY_INT64(numscans)
/* pg_stat_get_idx_tuples_returned */
PG_STAT_GET_IDXENTRY_INT64(tuples_returned)
/* pg_stat_get_idx_tuples_fetched */
PG_STAT_GET_IDXENTRY_INT64(tuples_fetched)
/* pg_stat_get_idx_blocks_fetched */
PG_STAT_GET_IDXENTRY_INT64(blocks_fetched)
/* pg_stat_get_idx_blocks_hit */
PG_STAT_GET_IDXENTRY_INT64(blocks_hit)
#define PG_STAT_GET_RELENTRY_FLOAT8(stat) \
Datum \
CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS) \
@@ -173,6 +207,34 @@ PG_STAT_GET_RELENTRY_TIMESTAMPTZ(lastscan)
/* pg_stat_get_stat_reset_time */
PG_STAT_GET_RELENTRY_TIMESTAMPTZ(stat_reset_time)
/*
* Accessor macro for index timestamp fields.
*/
#define PG_STAT_GET_IDXENTRY_TIMESTAMPTZ(stat) \
Datum \
CppConcat(pg_stat_get_idx_,stat)(PG_FUNCTION_ARGS) \
{ \
Oid relid = PG_GETARG_OID(0); \
TimestampTz result; \
PgStat_StatIdxEntry *idxentry; \
\
if ((idxentry = pgstat_fetch_stat_idxentry(relid)) == NULL) \
result = 0; \
else \
result = idxentry->stat; \
\
if (result == 0) \
PG_RETURN_NULL(); \
else \
PG_RETURN_TIMESTAMPTZ(result); \
}
/* pg_stat_get_idx_lastscan */
PG_STAT_GET_IDXENTRY_TIMESTAMPTZ(lastscan)
/* pg_stat_get_idx_stat_reset_time */
PG_STAT_GET_IDXENTRY_TIMESTAMPTZ(stat_reset_time)
Datum
pg_stat_get_function_calls(PG_FUNCTION_ARGS)
{
@@ -1906,6 +1968,41 @@ PG_STAT_GET_XACT_RELENTRY_INT64(tuples_updated)
/* pg_stat_get_xact_tuples_deleted */
PG_STAT_GET_XACT_RELENTRY_INT64(tuples_deleted)
/*
* Accessor macro for in-transaction index stats.
*/
#define PG_STAT_GET_XACT_IDXENTRY_INT64(stat) \
Datum \
CppConcat(pg_stat_get_xact_idx_,stat)(PG_FUNCTION_ARGS) \
{ \
Oid relid = PG_GETARG_OID(0); \
int64 result; \
PgStat_TableStatus *tabentry; \
\
tabentry = find_tabstat_entry_kind(PGSTAT_KIND_INDEX, relid); \
if (!tabentry) \
result = 0; \
else \
result = (int64) (tabentry->counts.stat); \
\
PG_RETURN_INT64(result); \
}
/* pg_stat_get_xact_idx_numscans */
PG_STAT_GET_XACT_IDXENTRY_INT64(numscans)
/* pg_stat_get_xact_idx_tuples_returned */
PG_STAT_GET_XACT_IDXENTRY_INT64(tuples_returned)
/* pg_stat_get_xact_idx_tuples_fetched */
PG_STAT_GET_XACT_IDXENTRY_INT64(tuples_fetched)
/* pg_stat_get_xact_idx_blocks_fetched */
PG_STAT_GET_XACT_IDXENTRY_INT64(blocks_fetched)
/* pg_stat_get_xact_idx_blocks_hit */
PG_STAT_GET_XACT_IDXENTRY_INT64(blocks_hit)
Datum
pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS)
{
@@ -2047,6 +2144,17 @@ pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
PG_RETURN_VOID();
}
Datum
pg_stat_reset_single_index_counters(PG_FUNCTION_ARGS)
{
Oid idxoid = PG_GETARG_OID(0);
Oid dboid = (IsSharedRelation(idxoid) ? InvalidOid : MyDatabaseId);
pgstat_reset(PGSTAT_KIND_INDEX, dboid, idxoid);
PG_RETURN_VOID();
}
Datum
pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
{

View File

@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202607273
#define CATALOG_VERSION_NO 202608121
#endif

View File

@@ -5555,11 +5555,11 @@
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',
{ oid => '1928', descr => 'statistics: number of scans done for table',
proname => 'pg_stat_get_numscans', provolatile => 's', proparallel => 'r',
prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_numscans' },
{ oid => '6310', descr => 'statistics: time of the last scan for table/index',
{ oid => '6310', descr => 'statistics: time of the last scan for table',
proname => 'pg_stat_get_lastscan', provolatile => 's', proparallel => 'r',
prorettype => 'timestamptz', proargtypes => 'oid',
prosrc => 'pg_stat_get_lastscan' },
@@ -6142,7 +6142,7 @@
prosrc => 'pg_stat_get_function_stat_reset_time' },
{ oid => '3037',
descr => 'statistics: number of scans done for table/index in current transaction',
descr => 'statistics: number of scans done for table in current transaction',
proname => 'pg_stat_get_xact_numscans', provolatile => 'v',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_xact_numscans' },
@@ -6234,10 +6234,71 @@
proargdefaults => '{NULL}', prosrc => 'pg_stat_reset_shared',
proacl => '{POSTGRES=X}' },
{ oid => '3776',
descr => 'statistics: reset collected statistics for a single table or index in the current database or shared across all databases in the cluster',
descr => 'statistics: reset collected statistics for a single table in the current database or shared across all databases in the cluster',
proname => 'pg_stat_reset_single_table_counters', provolatile => 'v',
prorettype => 'void', proargtypes => 'oid',
prosrc => 'pg_stat_reset_single_table_counters', proacl => '{POSTGRES=X}' },
{ oid => '8450',
descr => 'statistics: reset collected statistics for a single index in the current database or shared across all databases in the cluster',
proname => 'pg_stat_reset_single_index_counters', provolatile => 'v',
prorettype => 'void', proargtypes => 'oid',
prosrc => 'pg_stat_reset_single_index_counters', proacl => '{POSTGRES=X}' },
{ oid => '8451', descr => 'statistics: number of scans done for index',
proname => 'pg_stat_get_idx_numscans', provolatile => 's', proparallel => 'r',
prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_idx_numscans' },
{ oid => '8452',
descr => 'statistics: number of index entries returned by index',
proname => 'pg_stat_get_idx_tuples_returned', provolatile => 's',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_idx_tuples_returned' },
{ oid => '8453',
descr => 'statistics: number of tuples fetched from table by index',
proname => 'pg_stat_get_idx_tuples_fetched', provolatile => 's',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_idx_tuples_fetched' },
{ oid => '8454', descr => 'statistics: number of blocks fetched for index',
proname => 'pg_stat_get_idx_blocks_fetched', provolatile => 's',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_idx_blocks_fetched' },
{ oid => '8455',
descr => 'statistics: number of blocks found in cache for index',
proname => 'pg_stat_get_idx_blocks_hit', provolatile => 's',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_idx_blocks_hit' },
{ oid => '8456', descr => 'statistics: time of the last scan for index',
proname => 'pg_stat_get_idx_lastscan', provolatile => 's', proparallel => 'r',
prorettype => 'timestamptz', proargtypes => 'oid',
prosrc => 'pg_stat_get_idx_lastscan' },
{ oid => '8457', descr => 'statistics: last reset for an index',
proname => 'pg_stat_get_idx_stat_reset_time', provolatile => 's',
proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
prosrc => 'pg_stat_get_idx_stat_reset_time' },
{ oid => '8458',
descr => 'statistics: number of scans done for index in current transaction',
proname => 'pg_stat_get_xact_idx_numscans', provolatile => 'v',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_xact_idx_numscans' },
{ oid => '8459',
descr => 'statistics: number of index entries returned in current transaction',
proname => 'pg_stat_get_xact_idx_tuples_returned', provolatile => 'v',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_xact_idx_tuples_returned' },
{ oid => '8460',
descr => 'statistics: number of tuples fetched by index in current transaction',
proname => 'pg_stat_get_xact_idx_tuples_fetched', provolatile => 'v',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_xact_idx_tuples_fetched' },
{ oid => '8461',
descr => 'statistics: number of blocks fetched for index in current transaction',
proname => 'pg_stat_get_xact_idx_blocks_fetched', provolatile => 'v',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_xact_idx_blocks_fetched' },
{ oid => '8462',
descr => 'statistics: number of blocks found in cache for index in current transaction',
proname => 'pg_stat_get_xact_idx_blocks_hit', provolatile => 'v',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_xact_idx_blocks_hit' },
{ oid => '3777',
descr => 'statistics: reset collected statistics for a single function in the current database',
proname => 'pg_stat_reset_single_function_counters', provolatile => 'v',

View File

@@ -218,7 +218,7 @@ typedef struct PgStat_TableXactStatus
* ------------------------------------------------------------
*/
#define PGSTAT_FILE_FORMAT_ID 0x01A5BCBC
#define PGSTAT_FILE_FORMAT_ID 0x01A5BCBD
typedef struct PgStat_ArchiverStats
{
@@ -487,6 +487,20 @@ typedef struct PgStat_StatTabEntry
TimestampTz stat_reset_time;
} PgStat_StatTabEntry;
typedef struct PgStat_StatIdxEntry
{
PgStat_Counter numscans;
TimestampTz lastscan;
PgStat_Counter tuples_returned;
PgStat_Counter tuples_fetched;
PgStat_Counter blocks_fetched;
PgStat_Counter blocks_hit;
TimestampTz stat_reset_time;
} PgStat_StatIdxEntry;
/* ------
* PgStat_WalCounters WAL activity data gathered from WalUsage
*
@@ -779,6 +793,12 @@ extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry_ext(bool shared,
Oid reloid,
bool *may_free);
extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
extern PgStat_TableStatus *find_tabstat_entry_kind(PgStat_Kind kind, Oid rel_id);
extern PgStat_StatIdxEntry *pgstat_fetch_stat_idxentry(Oid relid);
extern PgStat_StatIdxEntry *pgstat_fetch_stat_idxentry_ext(bool shared,
Oid reloid,
bool *may_free);
/*

View File

@@ -508,6 +508,12 @@ typedef struct PgStatShared_Relation
PgStat_StatTabEntry stats;
} PgStatShared_Relation;
typedef struct PgStatShared_Index
{
PgStatShared_Common header;
PgStat_StatIdxEntry stats;
} PgStatShared_Index;
typedef struct PgStatShared_Function
{
PgStatShared_Common header;
@@ -789,6 +795,15 @@ extern void pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref);
extern void pgstat_relation_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
/*
* Functions in pgstat_index.c
*/
extern bool pgstat_index_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
extern void pgstat_index_delete_pending_cb(PgStat_EntryRef *entry_ref);
extern void pgstat_index_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
/*
* Functions in pgstat_replslot.c
*/

View File

@@ -26,19 +26,20 @@
/* stats for variable-numbered objects */
#define PGSTAT_KIND_DATABASE 1 /* database-wide statistics */
#define PGSTAT_KIND_RELATION 2 /* per-table statistics */
#define PGSTAT_KIND_FUNCTION 3 /* per-function statistics */
#define PGSTAT_KIND_REPLSLOT 4 /* per-slot statistics */
#define PGSTAT_KIND_SUBSCRIPTION 5 /* per-subscription statistics */
#define PGSTAT_KIND_BACKEND 6 /* per-backend statistics */
#define PGSTAT_KIND_INDEX 3 /* per-index statistics */
#define PGSTAT_KIND_FUNCTION 4 /* per-function statistics */
#define PGSTAT_KIND_REPLSLOT 5 /* per-slot statistics */
#define PGSTAT_KIND_SUBSCRIPTION 6 /* per-subscription statistics */
#define PGSTAT_KIND_BACKEND 7 /* per-backend statistics */
/* stats for fixed-numbered objects */
#define PGSTAT_KIND_ARCHIVER 7
#define PGSTAT_KIND_BGWRITER 8
#define PGSTAT_KIND_CHECKPOINTER 9
#define PGSTAT_KIND_IO 10
#define PGSTAT_KIND_LOCK 11
#define PGSTAT_KIND_SLRU 12
#define PGSTAT_KIND_WAL 13
#define PGSTAT_KIND_ARCHIVER 8
#define PGSTAT_KIND_BGWRITER 9
#define PGSTAT_KIND_CHECKPOINTER 10
#define PGSTAT_KIND_IO 11
#define PGSTAT_KIND_LOCK 12
#define PGSTAT_KIND_SLRU 13
#define PGSTAT_KIND_WAL 14
#define PGSTAT_KIND_BUILTIN_MIN PGSTAT_KIND_DATABASE
#define PGSTAT_KIND_BUILTIN_MAX PGSTAT_KIND_WAL

View File

@@ -1806,11 +1806,11 @@ 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_stat_reset_time(i.oid) AS stats_reset
pg_stat_get_idx_numscans(i.oid) AS idx_scan,
pg_stat_get_idx_lastscan(i.oid) AS last_idx_scan,
pg_stat_get_idx_tuples_returned(i.oid) AS idx_tup_read,
pg_stat_get_idx_tuples_fetched(i.oid) AS idx_tup_fetch,
pg_stat_get_idx_stat_reset_time(i.oid) AS stats_reset
FROM (((pg_class c
JOIN pg_index x ON ((c.oid = x.indrelid)))
JOIN pg_class i ON ((i.oid = x.indexrelid)))
@@ -1822,9 +1822,9 @@ pg_stat_all_tables| SELECT c.oid AS relid,
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,
(sum(pg_stat_get_idx_numscans(i.indexrelid)))::bigint AS idx_scan,
max(pg_stat_get_idx_lastscan(i.indexrelid)) AS last_idx_scan,
((sum(pg_stat_get_idx_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,
@@ -2455,8 +2455,8 @@ pg_stat_xact_all_tables| SELECT c.oid AS relid,
c.relname,
pg_stat_get_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_xact_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_xact_tuples_fetched(c.oid)) AS idx_tup_fetch,
(sum(pg_stat_get_xact_idx_numscans(i.indexrelid)))::bigint AS idx_scan,
((sum(pg_stat_get_xact_idx_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,
pg_stat_get_xact_tuples_deleted(c.oid) AS n_tup_del,
@@ -2509,9 +2509,9 @@ 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_stat_reset_time(i.oid) AS stats_reset
(pg_stat_get_idx_blocks_fetched(i.oid) - pg_stat_get_idx_blocks_hit(i.oid)) AS idx_blks_read,
pg_stat_get_idx_blocks_hit(i.oid) AS idx_blks_hit,
pg_stat_get_idx_stat_reset_time(i.oid) AS stats_reset
FROM (((pg_class c
JOIN pg_index x ON ((c.oid = x.indrelid)))
JOIN pg_class i ON ((i.oid = x.indexrelid)))
@@ -2541,12 +2541,12 @@ pg_statio_all_tables| SELECT c.oid AS relid,
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_idx_blocks_fetched(pg_index.indexrelid) - pg_stat_get_idx_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
(sum(pg_stat_get_idx_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_idx_blocks_fetched(pg_index.indexrelid) - pg_stat_get_idx_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
(sum(pg_stat_get_idx_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"]));

View File

@@ -116,18 +116,19 @@ SELECT id, name, fixed_amount,
----+--------------+--------------+-----------+---------------
1 | database | f | t | t
2 | relation | f | f | t
3 | function | f | f | t
4 | replslot | f | t | t
5 | subscription | f | t | t
6 | backend | f | t | f
7 | archiver | t | f | t
8 | bgwriter | t | f | t
9 | checkpointer | t | f | t
10 | io | t | f | t
11 | lock | t | f | t
12 | slru | t | f | t
13 | wal | t | f | t
(13 rows)
3 | index | f | f | t
4 | function | f | f | t
5 | replslot | f | t | t
6 | subscription | f | t | t
7 | backend | f | t | f
8 | archiver | t | f | t
9 | bgwriter | t | f | t
10 | checkpointer | t | f | t
11 | io | t | f | t
12 | lock | t | f | t
13 | slru | t | f | t
14 | wal | t | f | t
(14 rows)
-- ensure that both seqscan and indexscan plans are allowed
SET enable_seqscan TO on;
@@ -900,8 +901,8 @@ SELECT idx_scan, :'test_last_idx' < last_idx_scan AS idx_ok,
(1 row)
-- check that the stats in pg_stat_all_indexes are reset
SELECT pg_stat_reset_single_table_counters('test_last_scan_pkey'::regclass);
pg_stat_reset_single_table_counters
SELECT pg_stat_reset_single_index_counters('test_last_scan_pkey'::regclass);
pg_stat_reset_single_index_counters
-------------------------------------
(1 row)
@@ -1385,21 +1386,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
@@ -1415,14 +1416,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
@@ -1437,7 +1438,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
@@ -1445,7 +1446,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
@@ -1453,7 +1454,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
@@ -1461,7 +1462,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
@@ -1469,7 +1470,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

View File

@@ -398,7 +398,7 @@ SELECT idx_scan, :'test_last_idx' < last_idx_scan AS idx_ok,
FROM pg_stat_all_indexes WHERE indexrelid = 'test_last_scan_pkey'::regclass;
-- check that the stats in pg_stat_all_indexes are reset
SELECT pg_stat_reset_single_table_counters('test_last_scan_pkey'::regclass);
SELECT pg_stat_reset_single_index_counters('test_last_scan_pkey'::regclass);
SELECT idx_scan, stats_reset IS NOT NULL AS has_stats_reset
FROM pg_stat_all_indexes WHERE indexrelid = 'test_last_scan_pkey'::regclass;
@@ -619,40 +619,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;

View File

@@ -2325,6 +2325,7 @@ PgStatShared_CustomVarEntry
PgStatShared_Database
PgStatShared_Function
PgStatShared_HashEntry
PgStatShared_Index
PgStatShared_IO
PgStatShared_Lock
PgStatShared_Relation
@@ -2362,6 +2363,7 @@ PgStat_StatCustomFixedEntry
PgStat_StatCustomVarEntry
PgStat_StatDBEntry
PgStat_StatFuncEntry
PgStat_StatIdxEntry
PgStat_StatReplSlotEntry
PgStat_StatSubEntry
PgStat_StatTabEntry