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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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",
|
||||
|
||||
|
||||
131
src/backend/utils/activity/pgstat_index.c
Normal file
131
src/backend/utils/activity/pgstat_index.c
Normal 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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -57,6 +57,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 202607273
|
||||
#define CATALOG_VERSION_NO 202608121
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"]));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user