Age Owner Branch data TLA Line data Source code
1 : : /* -------------------------------------------------------------------------
2 : : *
3 : : * pgstat_index.c
4 : : * Implementation of index statistics.
5 : : *
6 : : * This file contains the implementation of index statistics.
7 : : *
8 : : * Copyright (c) 2001-2026, PostgreSQL Global Development Group
9 : : *
10 : : * IDENTIFICATION
11 : : * src/backend/utils/activity/pgstat_index.c
12 : : * -------------------------------------------------------------------------
13 : : */
14 : :
15 : : #include "postgres.h"
16 : :
17 : : #include "access/xact.h"
18 : : #include "catalog/catalog.h"
19 : : #include "utils/memutils.h"
20 : : #include "utils/pgstat_internal.h"
21 : : #include "utils/rel.h"
22 : : #include "utils/timestamp.h"
23 : :
24 : :
25 : : /*
26 : : * Flush out pending stats for an index entry.
27 : : *
28 : : * If nowait is true and the lock could not be immediately acquired, returns
29 : : * false without flushing the entry. Otherwise returns true.
30 : : *
31 : : * Some of the stats are copied to the corresponding pending database stats
32 : : * entry when successfully flushing.
33 : : */
34 : : bool
15 michael@paquier.xyz 35 :GNC 623884 : pgstat_index_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
36 : : {
37 : : Oid dboid;
38 : : PgStat_RelationStatus *lstats; /* pending stats entry */
39 : : PgStatShared_Index *shidxstats;
40 : : PgStat_StatIdxEntry *idxentry; /* index entry of shared stats */
41 : : PgStat_StatDBEntry *dbentry; /* pending database entry */
42 : :
43 : 623884 : dboid = entry_ref->shared_entry->key.dboid;
13 44 : 623884 : lstats = (PgStat_RelationStatus *) entry_ref->pending;
15 45 : 623884 : shidxstats = (PgStatShared_Index *) entry_ref->shared_stats;
46 : :
47 : : /*
48 : : * Ignore entries that didn't accumulate any actual counts, such as
49 : : * indexes that were opened by the planner but not used.
50 : : */
13 51 [ + + ]: 623884 : if (pg_memory_is_all_zeros(&lstats->idx,
52 : : sizeof(struct PgStat_IndexCounts)))
15 53 : 84 : return true;
54 : :
55 [ + + ]: 623800 : if (!pgstat_lock_entry(entry_ref, nowait))
56 : 1 : return false;
57 : :
58 : : /* Add the values to the shared entry. */
59 : 623799 : idxentry = &shidxstats->stats;
60 : :
13 61 : 623799 : idxentry->numscans += lstats->idx.numscans;
62 [ + + ]: 623799 : if (lstats->idx.numscans)
63 : : {
15 64 : 549455 : TimestampTz t = GetCurrentTransactionStopTimestamp();
65 : :
66 [ + + ]: 549455 : if (t > idxentry->lastscan)
67 : 540144 : idxentry->lastscan = t;
68 : : }
13 69 : 623799 : idxentry->tuples_returned += lstats->idx.tuples_returned;
70 : 623799 : idxentry->tuples_fetched += lstats->idx.tuples_fetched;
71 : 623799 : idxentry->blocks_fetched += lstats->idx.blocks_fetched;
72 : 623799 : idxentry->blocks_hit += lstats->idx.blocks_hit;
73 : :
15 74 : 623799 : pgstat_unlock_entry(entry_ref);
75 : :
76 : : /* The entry was successfully flushed, add the same to database stats */
77 : 623799 : dbentry = pgstat_prep_database_pending(dboid);
13 78 : 623799 : dbentry->tuples_returned += lstats->idx.tuples_returned;
79 : 623799 : dbentry->tuples_fetched += lstats->idx.tuples_fetched;
80 : 623799 : dbentry->blocks_fetched += lstats->idx.blocks_fetched;
81 : 623799 : dbentry->blocks_hit += lstats->idx.blocks_hit;
82 : :
15 83 : 623799 : return true;
84 : : }
85 : :
86 : : /*
87 : : * Callback to delete pending index stats.
88 : : */
89 : : void
90 : 638725 : pgstat_index_delete_pending_cb(PgStat_EntryRef *entry_ref)
91 : : {
13 92 : 638725 : PgStat_RelationStatus *pending = (PgStat_RelationStatus *) entry_ref->pending;
93 : :
15 94 [ + + ]: 638725 : if (pending->relation)
95 : 612308 : pgstat_unlink_relation(pending->relation);
96 : 638725 : }
97 : :
98 : : /*
99 : : * Callback to reset the timestamp on an index stats entry.
100 : : */
101 : : void
102 : 4032 : pgstat_index_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
103 : : {
104 : 4032 : ((PgStatShared_Index *) header)->stats.stat_reset_time = ts;
105 : 4032 : }
106 : :
107 : : /*
108 : : * Support function for the SQL-callable pgstat* functions. Returns
109 : : * the collected statistics for one index or NULL. NULL doesn't mean
110 : : * that the index doesn't exist, just that there are no statistics, so the
111 : : * caller is better off to report ZERO instead.
112 : : */
113 : : PgStat_StatIdxEntry *
114 : 195 : pgstat_fetch_stat_idxentry(Oid relid)
115 : : {
116 : 195 : return pgstat_fetch_stat_idxentry_ext(IsSharedRelation(relid), relid, NULL);
117 : : }
118 : :
119 : : /*
120 : : * More efficient version of pgstat_fetch_stat_idxentry(), allowing to specify
121 : : * whether the to-be-accessed index is a shared relation or not. This version
122 : : * also returns whether the caller can pfree() the result if desired.
123 : : */
124 : : PgStat_StatIdxEntry *
125 : 521 : pgstat_fetch_stat_idxentry_ext(bool shared, Oid reloid, bool *may_free)
126 : : {
127 [ - + ]: 521 : Oid dboid = (shared ? InvalidOid : MyDatabaseId);
128 : :
129 : 521 : return (PgStat_StatIdxEntry *)
130 : 521 : pgstat_fetch_entry(PGSTAT_KIND_INDEX, dboid, reloid, may_free);
131 : : }
|