diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 099e9b6f4e9..32cb6fdbd76 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -5877,6 +5877,24 @@ description | Waiting for a newly initialized WAL file to reach durable storage + + + + pg_stat_reset_single_index_counters + + pg_stat_reset_single_index_counters ( oid ) + void + + + Resets statistics for a single index in the current database + or shared across all databases in the cluster to zero. + + + This function is restricted to superusers by default, but other users + can be granted EXECUTE to run the function. + + + @@ -6022,7 +6040,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage void - 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. diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 090281a03dd..8612d99a890 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -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 diff --git a/src/backend/utils/activity/Makefile b/src/backend/utils/activity/Makefile index 5fed953c28a..2e32d1485d6 100644 --- a/src/backend/utils/activity/Makefile +++ b/src/backend/utils/activity/Makefile @@ -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 \ diff --git a/src/backend/utils/activity/meson.build b/src/backend/utils/activity/meson.build index 470b5dac402..e6dcb2e26fc 100644 --- a/src/backend/utils/activity/meson.build +++ b/src/backend/utils/activity/meson.build @@ -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', diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c index 50cd07822b4..fe1637e2095 100644 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@ -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", diff --git a/src/backend/utils/activity/pgstat_index.c b/src/backend/utils/activity/pgstat_index.c new file mode 100644 index 00000000000..ce7a7f0f56c --- /dev/null +++ b/src/backend/utils/activity/pgstat_index.c @@ -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); +} diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c index 04f2eb21d0b..beea9188773 100644 --- a/src/backend/utils/activity/pgstat_relation.c +++ b/src/backend/utils/activity/pgstat_relation.c @@ -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; diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 565d0e70768..946025f39ed 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -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) { diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index f20ea73ed39..93132521532 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202607273 +#define CATALOG_VERSION_NO 202608121 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index f8a021987b5..66c3c9a04cf 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -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', diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 58a44857f13..9c29dbe2c44 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -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); /* diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h index b0a17691966..1ef98620e1c 100644 --- a/src/include/utils/pgstat_internal.h +++ b/src/include/utils/pgstat_internal.h @@ -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 */ diff --git a/src/include/utils/pgstat_kind.h b/src/include/utils/pgstat_kind.h index 2d78a029683..45ca599d0dd 100644 --- a/src/include/utils/pgstat_kind.h +++ b/src/include/utils/pgstat_kind.h @@ -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 diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 6a3341356da..1a29d46213e 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -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"])); diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out index e230356de13..c682a9ed60a 100644 --- a/src/test/regress/expected/stats.out +++ b/src/test/regress/expected/stats.out @@ -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 diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql index 4c265d1245c..d4623c32cd3 100644 --- a/src/test/regress/sql/stats.sql +++ b/src/test/regress/sql/stats.sql @@ -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; diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index eb3dd5481e6..8e3213954d8 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -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