PostgreSQL Source Code  git master
pgstat_relation.c File Reference
#include "postgres.h"
#include "access/twophase_rmgr.h"
#include "access/xact.h"
#include "catalog/partition.h"
#include "postmaster/autovacuum.h"
#include "utils/memutils.h"
#include "utils/pgstat_internal.h"
#include "utils/rel.h"
#include "utils/timestamp.h"
#include "catalog/catalog.h"
Include dependency graph for pgstat_relation.c:

Go to the source code of this file.

Data Structures

struct  TwoPhasePgStatRecord
 

Typedefs

typedef struct TwoPhasePgStatRecord TwoPhasePgStatRecord
 

Functions

static PgStat_TableStatuspgstat_prep_relation_pending (Oid rel_id, bool isshared)
 
static void add_tabstat_xact_level (PgStat_TableStatus *pgstat_info, int nest_level)
 
static void ensure_tabstat_xact_level (PgStat_TableStatus *pgstat_info)
 
static void save_truncdrop_counters (PgStat_TableXactStatus *trans, bool is_drop)
 
static void restore_truncdrop_counters (PgStat_TableXactStatus *trans)
 
void pgstat_copy_relation_stats (Relation dst, Relation src)
 
void pgstat_init_relation (Relation rel)
 
void pgstat_assoc_relation (Relation rel)
 
void pgstat_unlink_relation (Relation rel)
 
void pgstat_create_relation (Relation rel)
 
void pgstat_drop_relation (Relation rel)
 
void pgstat_report_vacuum (Oid tableoid, bool shared, PgStat_Counter livetuples, PgStat_Counter deadtuples)
 
void pgstat_report_analyze (Relation rel, PgStat_Counter livetuples, PgStat_Counter deadtuples, bool resetcounter)
 
void pgstat_count_heap_insert (Relation rel, PgStat_Counter n)
 
void pgstat_count_heap_update (Relation rel, bool hot, bool newpage)
 
void pgstat_count_heap_delete (Relation rel)
 
void pgstat_count_truncate (Relation rel)
 
void pgstat_update_heap_dead_tuples (Relation rel, int delta)
 
PgStat_StatTabEntrypgstat_fetch_stat_tabentry (Oid relid)
 
PgStat_StatTabEntrypgstat_fetch_stat_tabentry_ext (bool shared, Oid reloid)
 
PgStat_TableStatusfind_tabstat_entry (Oid rel_id)
 
void AtEOXact_PgStat_Relations (PgStat_SubXactStatus *xact_state, bool isCommit)
 
void AtEOSubXact_PgStat_Relations (PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth)
 
void AtPrepare_PgStat_Relations (PgStat_SubXactStatus *xact_state)
 
void PostPrepare_PgStat_Relations (PgStat_SubXactStatus *xact_state)
 
void pgstat_twophase_postcommit (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
void pgstat_twophase_postabort (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
bool pgstat_relation_flush_cb (PgStat_EntryRef *entry_ref, bool nowait)
 
void pgstat_relation_delete_pending_cb (PgStat_EntryRef *entry_ref)
 

Typedef Documentation

◆ TwoPhasePgStatRecord

Function Documentation

◆ add_tabstat_xact_level()

static void add_tabstat_xact_level ( PgStat_TableStatus pgstat_info,
int  nest_level 
)
static

Definition at line 886 of file pgstat_relation.c.

887 {
888  PgStat_SubXactStatus *xact_state;
890 
891  /*
892  * If this is the first rel to be modified at the current nest level, we
893  * first have to push a transaction stack entry.
894  */
895  xact_state = pgstat_get_xact_stack_level(nest_level);
896 
897  /* Now make a per-table stack entry */
900  sizeof(PgStat_TableXactStatus));
901  trans->nest_level = nest_level;
902  trans->upper = pgstat_info->trans;
903  trans->parent = pgstat_info;
904  trans->next = xact_state->first;
905  xact_state->first = trans;
906  pgstat_info->trans = trans;
907 }
MemoryContext TopTransactionContext
Definition: mcxt.c:146
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1064
PgStat_SubXactStatus * pgstat_get_xact_stack_level(int nest_level)
Definition: pgstat_xact.c:237
PgStat_TableXactStatus * first
struct PgStat_TableXactStatus * trans
Definition: pgstat.h:201
static zic_t trans[TZ_MAX_LEAPS]
Definition: zic.c:402

References PgStat_SubXactStatus::first, MemoryContextAllocZero(), pgstat_get_xact_stack_level(), TopTransactionContext, PgStat_TableStatus::trans, and trans.

Referenced by ensure_tabstat_xact_level().

◆ AtEOSubXact_PgStat_Relations()

void AtEOSubXact_PgStat_Relations ( PgStat_SubXactStatus xact_state,
bool  isCommit,
int  nestDepth 
)

Definition at line 564 of file pgstat_relation.c.

565 {
567  PgStat_TableXactStatus *next_trans;
568 
569  for (trans = xact_state->first; trans != NULL; trans = next_trans)
570  {
571  PgStat_TableStatus *tabstat;
572 
573  next_trans = trans->next;
574  Assert(trans->nest_level == nestDepth);
575  tabstat = trans->parent;
576  Assert(tabstat->trans == trans);
577 
578  if (isCommit)
579  {
580  if (trans->upper && trans->upper->nest_level == nestDepth - 1)
581  {
582  if (trans->truncdropped)
583  {
584  /* propagate the truncate/drop status one level up */
585  save_truncdrop_counters(trans->upper, false);
586  /* replace upper xact stats with ours */
587  trans->upper->tuples_inserted = trans->tuples_inserted;
588  trans->upper->tuples_updated = trans->tuples_updated;
589  trans->upper->tuples_deleted = trans->tuples_deleted;
590  }
591  else
592  {
593  trans->upper->tuples_inserted += trans->tuples_inserted;
594  trans->upper->tuples_updated += trans->tuples_updated;
595  trans->upper->tuples_deleted += trans->tuples_deleted;
596  }
597  tabstat->trans = trans->upper;
598  pfree(trans);
599  }
600  else
601  {
602  /*
603  * When there isn't an immediate parent state, we can just
604  * reuse the record instead of going through a palloc/pfree
605  * pushup (this works since it's all in TopTransactionContext
606  * anyway). We have to re-link it into the parent level,
607  * though, and that might mean pushing a new entry into the
608  * pgStatXactStack.
609  */
610  PgStat_SubXactStatus *upper_xact_state;
611 
612  upper_xact_state = pgstat_get_xact_stack_level(nestDepth - 1);
613  trans->next = upper_xact_state->first;
614  upper_xact_state->first = trans;
615  trans->nest_level = nestDepth - 1;
616  }
617  }
618  else
619  {
620  /*
621  * On abort, update top-level tabstat counts, then forget the
622  * subtransaction
623  */
624 
625  /* first restore values obliterated by truncate/drop */
627  /* count attempted actions regardless of commit/abort */
628  tabstat->counts.tuples_inserted += trans->tuples_inserted;
629  tabstat->counts.tuples_updated += trans->tuples_updated;
630  tabstat->counts.tuples_deleted += trans->tuples_deleted;
631  /* inserted tuples are dead, deleted tuples are unaffected */
632  tabstat->counts.delta_dead_tuples +=
633  trans->tuples_inserted + trans->tuples_updated;
634  tabstat->trans = trans->upper;
635  pfree(trans);
636  }
637  }
638 }
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1456
static void save_truncdrop_counters(PgStat_TableXactStatus *trans, bool is_drop)
static void restore_truncdrop_counters(PgStat_TableXactStatus *trans)
PgStat_Counter tuples_inserted
Definition: pgstat.h:167
PgStat_Counter tuples_updated
Definition: pgstat.h:168
PgStat_Counter delta_dead_tuples
Definition: pgstat.h:175
PgStat_Counter tuples_deleted
Definition: pgstat.h:169
PgStat_TableCounts counts
Definition: pgstat.h:202

References Assert(), PgStat_TableStatus::counts, PgStat_TableCounts::delta_dead_tuples, PgStat_SubXactStatus::first, pfree(), pgstat_get_xact_stack_level(), restore_truncdrop_counters(), save_truncdrop_counters(), PgStat_TableStatus::trans, trans, PgStat_TableCounts::tuples_deleted, PgStat_TableCounts::tuples_inserted, and PgStat_TableCounts::tuples_updated.

Referenced by AtEOSubXact_PgStat().

◆ AtEOXact_PgStat_Relations()

void AtEOXact_PgStat_Relations ( PgStat_SubXactStatus xact_state,
bool  isCommit 
)

Definition at line 506 of file pgstat_relation.c.

507 {
509 
510  for (trans = xact_state->first; trans != NULL; trans = trans->next)
511  {
512  PgStat_TableStatus *tabstat;
513 
514  Assert(trans->nest_level == 1);
515  Assert(trans->upper == NULL);
516  tabstat = trans->parent;
517  Assert(tabstat->trans == trans);
518  /* restore pre-truncate/drop stats (if any) in case of aborted xact */
519  if (!isCommit)
521  /* count attempted actions regardless of commit/abort */
522  tabstat->counts.tuples_inserted += trans->tuples_inserted;
523  tabstat->counts.tuples_updated += trans->tuples_updated;
524  tabstat->counts.tuples_deleted += trans->tuples_deleted;
525  if (isCommit)
526  {
527  tabstat->counts.truncdropped = trans->truncdropped;
528  if (trans->truncdropped)
529  {
530  /* forget live/dead stats seen by backend thus far */
531  tabstat->counts.delta_live_tuples = 0;
532  tabstat->counts.delta_dead_tuples = 0;
533  }
534  /* insert adds a live tuple, delete removes one */
535  tabstat->counts.delta_live_tuples +=
536  trans->tuples_inserted - trans->tuples_deleted;
537  /* update and delete each create a dead tuple */
538  tabstat->counts.delta_dead_tuples +=
539  trans->tuples_updated + trans->tuples_deleted;
540  /* insert, update, delete each count as one change event */
541  tabstat->counts.changed_tuples +=
542  trans->tuples_inserted + trans->tuples_updated +
543  trans->tuples_deleted;
544  }
545  else
546  {
547  /* inserted tuples are dead, deleted tuples are unaffected */
548  tabstat->counts.delta_dead_tuples +=
549  trans->tuples_inserted + trans->tuples_updated;
550  /* an aborted xact generates no changed_tuple events */
551  }
552  tabstat->trans = NULL;
553  }
554 }
PgStat_Counter delta_live_tuples
Definition: pgstat.h:174
PgStat_Counter changed_tuples
Definition: pgstat.h:176

References Assert(), PgStat_TableCounts::changed_tuples, PgStat_TableStatus::counts, PgStat_TableCounts::delta_dead_tuples, PgStat_TableCounts::delta_live_tuples, PgStat_SubXactStatus::first, restore_truncdrop_counters(), PgStat_TableStatus::trans, trans, PgStat_TableCounts::truncdropped, PgStat_TableCounts::tuples_deleted, PgStat_TableCounts::tuples_inserted, and PgStat_TableCounts::tuples_updated.

Referenced by AtEOXact_PgStat().

◆ AtPrepare_PgStat_Relations()

void AtPrepare_PgStat_Relations ( PgStat_SubXactStatus xact_state)

Definition at line 645 of file pgstat_relation.c.

646 {
648 
649  for (trans = xact_state->first; trans != NULL; trans = trans->next)
650  {
652  TwoPhasePgStatRecord record;
653 
654  Assert(trans->nest_level == 1);
655  Assert(trans->upper == NULL);
656  tabstat = trans->parent;
657  Assert(tabstat->trans == trans);
658 
659  record.tuples_inserted = trans->tuples_inserted;
660  record.tuples_updated = trans->tuples_updated;
661  record.tuples_deleted = trans->tuples_deleted;
662  record.inserted_pre_truncdrop = trans->inserted_pre_truncdrop;
663  record.updated_pre_truncdrop = trans->updated_pre_truncdrop;
664  record.deleted_pre_truncdrop = trans->deleted_pre_truncdrop;
665  record.id = tabstat->id;
666  record.shared = tabstat->shared;
667  record.truncdropped = trans->truncdropped;
668 
670  &record, sizeof(TwoPhasePgStatRecord));
671  }
672 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:166
PgStat_Counter deleted_pre_truncdrop
PgStat_Counter inserted_pre_truncdrop
PgStat_Counter updated_pre_truncdrop
PgStat_Counter tuples_deleted
PgStat_Counter tuples_inserted
PgStat_Counter tuples_updated
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1257
#define TWOPHASE_RM_PGSTAT_ID
Definition: twophase_rmgr.h:26

References Assert(), TwoPhasePgStatRecord::deleted_pre_truncdrop, PgStat_SubXactStatus::first, TwoPhasePgStatRecord::id, TwoPhasePgStatRecord::inserted_pre_truncdrop, PG_USED_FOR_ASSERTS_ONLY, RegisterTwoPhaseRecord(), TwoPhasePgStatRecord::shared, trans, TwoPhasePgStatRecord::truncdropped, TwoPhasePgStatRecord::tuples_deleted, TwoPhasePgStatRecord::tuples_inserted, TwoPhasePgStatRecord::tuples_updated, TWOPHASE_RM_PGSTAT_ID, and TwoPhasePgStatRecord::updated_pre_truncdrop.

Referenced by AtPrepare_PgStat().

◆ ensure_tabstat_xact_level()

static void ensure_tabstat_xact_level ( PgStat_TableStatus pgstat_info)
static

Definition at line 913 of file pgstat_relation.c.

914 {
915  int nest_level = GetCurrentTransactionNestLevel();
916 
917  if (pgstat_info->trans == NULL ||
918  pgstat_info->trans->nest_level != nest_level)
919  add_tabstat_xact_level(pgstat_info, nest_level);
920 }
static void add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:914

References add_tabstat_xact_level(), GetCurrentTransactionNestLevel(), PgStat_TableXactStatus::nest_level, and PgStat_TableStatus::trans.

Referenced by pgstat_count_heap_delete(), pgstat_count_heap_insert(), pgstat_count_heap_update(), and pgstat_count_truncate().

◆ find_tabstat_entry()

PgStat_TableStatus* find_tabstat_entry ( Oid  rel_id)

Definition at line 484 of file pgstat_relation.c.

485 {
486  PgStat_EntryRef *entry_ref;
487 
489  if (!entry_ref)
491 
492  if (entry_ref)
493  return entry_ref->pending;
494  return NULL;
495 }
Oid MyDatabaseId
Definition: globals.c:89
PgStat_EntryRef * pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
Definition: pgstat.c:1132
@ PGSTAT_KIND_RELATION
Definition: pgstat.h:42
#define InvalidOid
Definition: postgres_ext.h:36

References InvalidOid, MyDatabaseId, PgStat_EntryRef::pending, pgstat_fetch_pending_entry(), and PGSTAT_KIND_RELATION.

Referenced by pg_stat_get_xact_tuples_deleted(), pg_stat_get_xact_tuples_inserted(), and pg_stat_get_xact_tuples_updated().

◆ pgstat_assoc_relation()

void pgstat_assoc_relation ( Relation  rel)

Definition at line 133 of file pgstat_relation.c.

134 {
135  Assert(rel->pgstat_enabled);
136  Assert(rel->pgstat_info == NULL);
137 
138  /* Else find or make the PgStat_TableStatus entry, and update link */
140  rel->rd_rel->relisshared);
141 
142  /* don't allow link a stats to multiple relcache entries */
143  Assert(rel->pgstat_info->relation == NULL);
144 
145  /* mark this relation as the owner */
146  rel->pgstat_info->relation = rel;
147 }
static PgStat_TableStatus * pgstat_prep_relation_pending(Oid rel_id, bool isshared)
#define RelationGetRelid(relation)
Definition: rel.h:504
Relation relation
Definition: pgstat.h:203
bool pgstat_enabled
Definition: rel.h:252
Form_pg_class rd_rel
Definition: rel.h:111
struct PgStat_TableStatus * pgstat_info
Definition: rel.h:254

References Assert(), RelationData::pgstat_enabled, RelationData::pgstat_info, pgstat_prep_relation_pending(), RelationData::rd_rel, PgStat_TableStatus::relation, and RelationGetRelid.

◆ pgstat_copy_relation_stats()

void pgstat_copy_relation_stats ( Relation  dst,
Relation  src 
)

Definition at line 59 of file pgstat_relation.c.

60 {
61  PgStat_StatTabEntry *srcstats;
62  PgStatShared_Relation *dstshstats;
63  PgStat_EntryRef *dst_ref;
64 
65  srcstats = pgstat_fetch_stat_tabentry_ext(src->rd_rel->relisshared,
66  RelationGetRelid(src));
67  if (!srcstats)
68  return;
69 
71  dst->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
72  RelationGetRelid(dst),
73  false);
74 
75  dstshstats = (PgStatShared_Relation *) dst_ref->shared_stats;
76  dstshstats->stats = *srcstats;
77 
78  pgstat_unlock_entry(dst_ref);
79 }
PgStat_StatTabEntry * pgstat_fetch_stat_tabentry_ext(bool shared, Oid reloid)
void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat_shmem.c:603
PgStat_EntryRef * pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, Oid objoid, bool nowait)
Definition: pgstat_shmem.c:612
PgStat_StatTabEntry stats
PgStatShared_Common * shared_stats

References InvalidOid, MyDatabaseId, pgstat_fetch_stat_tabentry_ext(), pgstat_get_entry_ref_locked(), PGSTAT_KIND_RELATION, pgstat_unlock_entry(), RelationData::rd_rel, RelationGetRelid, PgStat_EntryRef::shared_stats, and PgStatShared_Relation::stats.

Referenced by index_concurrently_swap().

◆ pgstat_count_heap_delete()

void pgstat_count_heap_delete ( Relation  rel)

Definition at line 402 of file pgstat_relation.c.

403 {
405  {
406  PgStat_TableStatus *pgstat_info = rel->pgstat_info;
407 
408  ensure_tabstat_xact_level(pgstat_info);
409  pgstat_info->trans->tuples_deleted++;
410  }
411 }
#define pgstat_should_count_relation(rel)
Definition: pgstat.h:602
static void ensure_tabstat_xact_level(PgStat_TableStatus *pgstat_info)
PgStat_Counter tuples_deleted
Definition: pgstat.h:214

References ensure_tabstat_xact_level(), RelationData::pgstat_info, pgstat_should_count_relation, PgStat_TableStatus::trans, and PgStat_TableXactStatus::tuples_deleted.

Referenced by heap_abort_speculative(), and heap_delete().

◆ pgstat_count_heap_insert()

void pgstat_count_heap_insert ( Relation  rel,
PgStat_Counter  n 
)

Definition at line 361 of file pgstat_relation.c.

362 {
364  {
365  PgStat_TableStatus *pgstat_info = rel->pgstat_info;
366 
367  ensure_tabstat_xact_level(pgstat_info);
368  pgstat_info->trans->tuples_inserted += n;
369  }
370 }
PgStat_Counter tuples_inserted
Definition: pgstat.h:212

References ensure_tabstat_xact_level(), RelationData::pgstat_info, pgstat_should_count_relation, PgStat_TableStatus::trans, and PgStat_TableXactStatus::tuples_inserted.

Referenced by ExecRefreshMatView(), heap_insert(), and heap_multi_insert().

◆ pgstat_count_heap_update()

void pgstat_count_heap_update ( Relation  rel,
bool  hot,
bool  newpage 
)

Definition at line 376 of file pgstat_relation.c.

377 {
378  Assert(!(hot && newpage));
379 
381  {
382  PgStat_TableStatus *pgstat_info = rel->pgstat_info;
383 
384  ensure_tabstat_xact_level(pgstat_info);
385  pgstat_info->trans->tuples_updated++;
386 
387  /*
388  * tuples_hot_updated and tuples_newpage_updated counters are
389  * nontransactional, so just advance them
390  */
391  if (hot)
392  pgstat_info->counts.tuples_hot_updated++;
393  else if (newpage)
394  pgstat_info->counts.tuples_newpage_updated++;
395  }
396 }
PgStat_Counter tuples_hot_updated
Definition: pgstat.h:170
PgStat_Counter tuples_newpage_updated
Definition: pgstat.h:171
PgStat_Counter tuples_updated
Definition: pgstat.h:213

References Assert(), PgStat_TableStatus::counts, ensure_tabstat_xact_level(), RelationData::pgstat_info, pgstat_should_count_relation, PgStat_TableStatus::trans, PgStat_TableCounts::tuples_hot_updated, PgStat_TableCounts::tuples_newpage_updated, and PgStat_TableXactStatus::tuples_updated.

Referenced by heap_update().

◆ pgstat_count_truncate()

void pgstat_count_truncate ( Relation  rel)

◆ pgstat_create_relation()

void pgstat_create_relation ( Relation  rel)

Definition at line 170 of file pgstat_relation.c.

171 {
173  rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
174  RelationGetRelid(rel));
175 }
void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
Definition: pgstat_xact.c:358

References InvalidOid, MyDatabaseId, pgstat_create_transactional(), PGSTAT_KIND_RELATION, RelationData::rd_rel, and RelationGetRelid.

Referenced by heap_create().

◆ pgstat_drop_relation()

void pgstat_drop_relation ( Relation  rel)

Definition at line 181 of file pgstat_relation.c.

182 {
183  int nest_level = GetCurrentTransactionNestLevel();
184  PgStat_TableStatus *pgstat_info;
185 
187  rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
188  RelationGetRelid(rel));
189 
191  return;
192 
193  /*
194  * Transactionally set counters to 0. That ensures that accesses to
195  * pg_stat_xact_all_tables inside the transaction show 0.
196  */
197  pgstat_info = rel->pgstat_info;
198  if (pgstat_info->trans &&
199  pgstat_info->trans->nest_level == nest_level)
200  {
201  save_truncdrop_counters(pgstat_info->trans, true);
202  pgstat_info->trans->tuples_inserted = 0;
203  pgstat_info->trans->tuples_updated = 0;
204  pgstat_info->trans->tuples_deleted = 0;
205  }
206 }
void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
Definition: pgstat_xact.c:380

References GetCurrentTransactionNestLevel(), InvalidOid, MyDatabaseId, PgStat_TableXactStatus::nest_level, pgstat_drop_transactional(), RelationData::pgstat_info, PGSTAT_KIND_RELATION, pgstat_should_count_relation, RelationData::rd_rel, RelationGetRelid, save_truncdrop_counters(), PgStat_TableStatus::trans, PgStat_TableXactStatus::tuples_deleted, PgStat_TableXactStatus::tuples_inserted, and PgStat_TableXactStatus::tuples_updated.

Referenced by heap_drop_with_catalog(), and index_drop().

◆ pgstat_fetch_stat_tabentry()

PgStat_StatTabEntry* pgstat_fetch_stat_tabentry ( Oid  relid)

Definition at line 457 of file pgstat_relation.c.

458 {
459  return pgstat_fetch_stat_tabentry_ext(IsSharedRelation(relid), relid);
460 }
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:245

References IsSharedRelation(), and pgstat_fetch_stat_tabentry_ext().

◆ pgstat_fetch_stat_tabentry_ext()

PgStat_StatTabEntry* pgstat_fetch_stat_tabentry_ext ( bool  shared,
Oid  reloid 
)

Definition at line 467 of file pgstat_relation.c.

468 {
469  Oid dboid = (shared ? InvalidOid : MyDatabaseId);
470 
471  return (PgStat_StatTabEntry *)
473 }
void * pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
Definition: pgstat.c:804
unsigned int Oid
Definition: postgres_ext.h:31

References InvalidOid, MyDatabaseId, pgstat_fetch_entry(), and PGSTAT_KIND_RELATION.

Referenced by do_autovacuum(), pgstat_copy_relation_stats(), pgstat_fetch_stat_tabentry(), and recheck_relation_needs_vacanalyze().

◆ pgstat_init_relation()

void pgstat_init_relation ( Relation  rel)

Definition at line 93 of file pgstat_relation.c.

94 {
95  char relkind = rel->rd_rel->relkind;
96 
97  /*
98  * We only count stats for relations with storage and partitioned tables
99  */
100  if (!RELKIND_HAS_STORAGE(relkind) && relkind != RELKIND_PARTITIONED_TABLE)
101  {
102  rel->pgstat_enabled = false;
103  rel->pgstat_info = NULL;
104  return;
105  }
106 
107  if (!pgstat_track_counts)
108  {
109  if (rel->pgstat_info)
111 
112  /* We're not counting at all */
113  rel->pgstat_enabled = false;
114  rel->pgstat_info = NULL;
115  return;
116  }
117 
118  rel->pgstat_enabled = true;
119 }
bool pgstat_track_counts
Definition: pgstat.c:187
void pgstat_unlink_relation(Relation rel)

References RelationData::pgstat_enabled, RelationData::pgstat_info, pgstat_track_counts, pgstat_unlink_relation(), and RelationData::rd_rel.

Referenced by relation_open(), and try_relation_open().

◆ pgstat_prep_relation_pending()

static PgStat_TableStatus * pgstat_prep_relation_pending ( Oid  rel_id,
bool  isshared 
)
static

Definition at line 867 of file pgstat_relation.c.

868 {
869  PgStat_EntryRef *entry_ref;
870  PgStat_TableStatus *pending;
871 
873  isshared ? InvalidOid : MyDatabaseId,
874  rel_id, NULL);
875  pending = entry_ref->pending;
876  pending->id = rel_id;
877  pending->shared = isshared;
878 
879  return pending;
880 }
PgStat_EntryRef * pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created_entry)
Definition: pgstat.c:1094

References PgStat_TableStatus::id, InvalidOid, MyDatabaseId, PgStat_EntryRef::pending, PGSTAT_KIND_RELATION, pgstat_prep_pending_entry(), and PgStat_TableStatus::shared.

Referenced by pgstat_assoc_relation(), pgstat_twophase_postabort(), and pgstat_twophase_postcommit().

◆ pgstat_relation_delete_pending_cb()

void pgstat_relation_delete_pending_cb ( PgStat_EntryRef entry_ref)

Definition at line 854 of file pgstat_relation.c.

855 {
856  PgStat_TableStatus *pending = (PgStat_TableStatus *) entry_ref->pending;
857 
858  if (pending->relation)
860 }
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77

References if(), PgStat_EntryRef::pending, pgstat_unlink_relation(), and PgStat_TableStatus::relation.

◆ pgstat_relation_flush_cb()

bool pgstat_relation_flush_cb ( PgStat_EntryRef entry_ref,
bool  nowait 
)

Definition at line 771 of file pgstat_relation.c.

772 {
773  static const PgStat_TableCounts all_zeroes;
774  Oid dboid;
775  PgStat_TableStatus *lstats; /* pending stats entry */
776  PgStatShared_Relation *shtabstats;
777  PgStat_StatTabEntry *tabentry; /* table entry of shared stats */
778  PgStat_StatDBEntry *dbentry; /* pending database entry */
779 
780  dboid = entry_ref->shared_entry->key.dboid;
781  lstats = (PgStat_TableStatus *) entry_ref->pending;
782  shtabstats = (PgStatShared_Relation *) entry_ref->shared_stats;
783 
784  /*
785  * Ignore entries that didn't accumulate any actual counts, such as
786  * indexes that were opened by the planner but not used.
787  */
788  if (memcmp(&lstats->counts, &all_zeroes,
789  sizeof(PgStat_TableCounts)) == 0)
790  {
791  return true;
792  }
793 
794  if (!pgstat_lock_entry(entry_ref, nowait))
795  return false;
796 
797  /* add the values to the shared entry. */
798  tabentry = &shtabstats->stats;
799 
800  tabentry->numscans += lstats->counts.numscans;
801  if (lstats->counts.numscans)
802  {
804 
805  if (t > tabentry->lastscan)
806  tabentry->lastscan = t;
807  }
808  tabentry->tuples_returned += lstats->counts.tuples_returned;
809  tabentry->tuples_fetched += lstats->counts.tuples_fetched;
810  tabentry->tuples_inserted += lstats->counts.tuples_inserted;
811  tabentry->tuples_updated += lstats->counts.tuples_updated;
812  tabentry->tuples_deleted += lstats->counts.tuples_deleted;
813  tabentry->tuples_hot_updated += lstats->counts.tuples_hot_updated;
815 
816  /*
817  * If table was truncated/dropped, first reset the live/dead counters.
818  */
819  if (lstats->counts.truncdropped)
820  {
821  tabentry->live_tuples = 0;
822  tabentry->dead_tuples = 0;
823  tabentry->ins_since_vacuum = 0;
824  }
825 
826  tabentry->live_tuples += lstats->counts.delta_live_tuples;
827  tabentry->dead_tuples += lstats->counts.delta_dead_tuples;
828  tabentry->mod_since_analyze += lstats->counts.changed_tuples;
829  tabentry->ins_since_vacuum += lstats->counts.tuples_inserted;
830  tabentry->blocks_fetched += lstats->counts.blocks_fetched;
831  tabentry->blocks_hit += lstats->counts.blocks_hit;
832 
833  /* Clamp live_tuples in case of negative delta_live_tuples */
834  tabentry->live_tuples = Max(tabentry->live_tuples, 0);
835  /* Likewise for dead_tuples */
836  tabentry->dead_tuples = Max(tabentry->dead_tuples, 0);
837 
838  pgstat_unlock_entry(entry_ref);
839 
840  /* The entry was successfully flushed, add the same to database stats */
841  dbentry = pgstat_prep_database_pending(dboid);
842  dbentry->tuples_returned += lstats->counts.tuples_returned;
843  dbentry->tuples_fetched += lstats->counts.tuples_fetched;
844  dbentry->tuples_inserted += lstats->counts.tuples_inserted;
845  dbentry->tuples_updated += lstats->counts.tuples_updated;
846  dbentry->tuples_deleted += lstats->counts.tuples_deleted;
847  dbentry->blocks_fetched += lstats->counts.blocks_fetched;
848  dbentry->blocks_hit += lstats->counts.blocks_hit;
849 
850  return true;
851 }
#define Max(x, y)
Definition: c.h:982
int64 TimestampTz
Definition: timestamp.h:39
PgStat_StatDBEntry * pgstat_prep_database_pending(Oid dboid)
bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait)
Definition: pgstat_shmem.c:575
PgStatShared_HashEntry * shared_entry
PgStat_Counter tuples_updated
Definition: pgstat.h:330
PgStat_Counter tuples_inserted
Definition: pgstat.h:329
PgStat_Counter tuples_returned
Definition: pgstat.h:327
PgStat_Counter blocks_hit
Definition: pgstat.h:326
PgStat_Counter blocks_fetched
Definition: pgstat.h:325
PgStat_Counter tuples_deleted
Definition: pgstat.h:331
PgStat_Counter tuples_fetched
Definition: pgstat.h:328
PgStat_Counter tuples_fetched
Definition: pgstat.h:403
PgStat_Counter ins_since_vacuum
Definition: pgstat.h:414
PgStat_Counter blocks_hit
Definition: pgstat.h:417
PgStat_Counter mod_since_analyze
Definition: pgstat.h:413
PgStat_Counter tuples_deleted
Definition: pgstat.h:407
PgStat_Counter tuples_hot_updated
Definition: pgstat.h:408
PgStat_Counter tuples_updated
Definition: pgstat.h:406
PgStat_Counter live_tuples
Definition: pgstat.h:411
PgStat_Counter numscans
Definition: pgstat.h:399
PgStat_Counter dead_tuples
Definition: pgstat.h:412
PgStat_Counter blocks_fetched
Definition: pgstat.h:416
PgStat_Counter tuples_returned
Definition: pgstat.h:402
TimestampTz lastscan
Definition: pgstat.h:400
PgStat_Counter tuples_inserted
Definition: pgstat.h:405
PgStat_Counter tuples_newpage_updated
Definition: pgstat.h:409
PgStat_Counter blocks_hit
Definition: pgstat.h:179
PgStat_Counter numscans
Definition: pgstat.h:162
PgStat_Counter tuples_returned
Definition: pgstat.h:164
PgStat_Counter blocks_fetched
Definition: pgstat.h:178
PgStat_Counter tuples_fetched
Definition: pgstat.h:165
TimestampTz GetCurrentTransactionStopTimestamp(void)
Definition: xact.c:876

References PgStat_TableCounts::blocks_fetched, PgStat_StatDBEntry::blocks_fetched, PgStat_StatTabEntry::blocks_fetched, PgStat_TableCounts::blocks_hit, PgStat_StatDBEntry::blocks_hit, PgStat_StatTabEntry::blocks_hit, PgStat_TableCounts::changed_tuples, PgStat_TableStatus::counts, PgStat_HashKey::dboid, PgStat_StatTabEntry::dead_tuples, PgStat_TableCounts::delta_dead_tuples, PgStat_TableCounts::delta_live_tuples, GetCurrentTransactionStopTimestamp(), PgStat_StatTabEntry::ins_since_vacuum, PgStatShared_HashEntry::key, PgStat_StatTabEntry::lastscan, PgStat_StatTabEntry::live_tuples, Max, PgStat_StatTabEntry::mod_since_analyze, PgStat_TableCounts::numscans, PgStat_StatTabEntry::numscans, PgStat_EntryRef::pending, pgstat_lock_entry(), pgstat_prep_database_pending(), pgstat_unlock_entry(), PgStat_EntryRef::shared_entry, PgStat_EntryRef::shared_stats, PgStatShared_Relation::stats, PgStat_TableCounts::truncdropped, PgStat_TableCounts::tuples_deleted, PgStat_StatDBEntry::tuples_deleted, PgStat_StatTabEntry::tuples_deleted, PgStat_TableCounts::tuples_fetched, PgStat_StatDBEntry::tuples_fetched, PgStat_StatTabEntry::tuples_fetched, PgStat_TableCounts::tuples_hot_updated, PgStat_StatTabEntry::tuples_hot_updated, PgStat_TableCounts::tuples_inserted, PgStat_StatDBEntry::tuples_inserted, PgStat_StatTabEntry::tuples_inserted, PgStat_TableCounts::tuples_newpage_updated, PgStat_StatTabEntry::tuples_newpage_updated, PgStat_TableCounts::tuples_returned, PgStat_StatDBEntry::tuples_returned, PgStat_StatTabEntry::tuples_returned, PgStat_TableCounts::tuples_updated, PgStat_StatDBEntry::tuples_updated, and PgStat_StatTabEntry::tuples_updated.

◆ pgstat_report_analyze()

void pgstat_report_analyze ( Relation  rel,
PgStat_Counter  livetuples,
PgStat_Counter  deadtuples,
bool  resetcounter 
)

Definition at line 278 of file pgstat_relation.c.

281 {
282  PgStat_EntryRef *entry_ref;
283  PgStatShared_Relation *shtabentry;
284  PgStat_StatTabEntry *tabentry;
285  Oid dboid = (rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId);
286 
287  if (!pgstat_track_counts)
288  return;
289 
290  /*
291  * Unlike VACUUM, ANALYZE might be running inside a transaction that has
292  * already inserted and/or deleted rows in the target table. ANALYZE will
293  * have counted such rows as live or dead respectively. Because we will
294  * report our counts of such rows at transaction end, we should subtract
295  * off these counts from the update we're making now, else they'll be
296  * double-counted after commit. (This approach also ensures that the
297  * shared stats entry ends up with the right numbers if we abort instead
298  * of committing.)
299  *
300  * Waste no time on partitioned tables, though.
301  */
302  if (pgstat_should_count_relation(rel) &&
303  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
304  {
306 
307  for (trans = rel->pgstat_info->trans; trans; trans = trans->upper)
308  {
309  livetuples -= trans->tuples_inserted - trans->tuples_deleted;
310  deadtuples -= trans->tuples_updated + trans->tuples_deleted;
311  }
312  /* count stuff inserted by already-aborted subxacts, too */
313  deadtuples -= rel->pgstat_info->counts.delta_dead_tuples;
314  /* Since ANALYZE's counts are estimates, we could have underflowed */
315  livetuples = Max(livetuples, 0);
316  deadtuples = Max(deadtuples, 0);
317  }
318 
319  /* block acquiring lock for the same reason as pgstat_report_autovac() */
321  RelationGetRelid(rel),
322  false);
323  /* can't get dropped while accessed */
324  Assert(entry_ref != NULL && entry_ref->shared_stats != NULL);
325 
326  shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
327  tabentry = &shtabentry->stats;
328 
329  tabentry->live_tuples = livetuples;
330  tabentry->dead_tuples = deadtuples;
331 
332  /*
333  * If commanded, reset mod_since_analyze to zero. This forgets any
334  * changes that were committed while the ANALYZE was in progress, but we
335  * have no good way to estimate how many of those there were.
336  */
337  if (resetcounter)
338  tabentry->mod_since_analyze = 0;
339 
341  {
343  tabentry->autoanalyze_count++;
344  }
345  else
346  {
348  tabentry->analyze_count++;
349  }
350 
351  pgstat_unlock_entry(entry_ref);
352 
353  /* see pgstat_report_vacuum() */
354  pgstat_flush_io(false);
355 }
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3385
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
bool pgstat_flush_io(bool nowait)
Definition: pgstat_io.c:159
PgStat_Counter analyze_count
Definition: pgstat.h:424
TimestampTz last_analyze_time
Definition: pgstat.h:423
PgStat_Counter autoanalyze_count
Definition: pgstat.h:426
TimestampTz last_autoanalyze_time
Definition: pgstat.h:425

References PgStat_StatTabEntry::analyze_count, Assert(), PgStat_StatTabEntry::autoanalyze_count, PgStat_TableStatus::counts, PgStat_StatTabEntry::dead_tuples, PgStat_TableCounts::delta_dead_tuples, GetCurrentTimestamp(), if(), InvalidOid, IsAutoVacuumWorkerProcess(), PgStat_StatTabEntry::last_analyze_time, PgStat_StatTabEntry::last_autoanalyze_time, PgStat_StatTabEntry::live_tuples, Max, PgStat_StatTabEntry::mod_since_analyze, MyDatabaseId, pgstat_flush_io(), pgstat_get_entry_ref_locked(), RelationData::pgstat_info, PGSTAT_KIND_RELATION, pgstat_should_count_relation, pgstat_track_counts, pgstat_unlock_entry(), RelationData::rd_rel, RelationGetRelid, PgStat_EntryRef::shared_stats, PgStatShared_Relation::stats, PgStat_TableStatus::trans, and trans.

Referenced by do_analyze_rel().

◆ pgstat_report_vacuum()

void pgstat_report_vacuum ( Oid  tableoid,
bool  shared,
PgStat_Counter  livetuples,
PgStat_Counter  deadtuples 
)

Definition at line 212 of file pgstat_relation.c.

214 {
215  PgStat_EntryRef *entry_ref;
216  PgStatShared_Relation *shtabentry;
217  PgStat_StatTabEntry *tabentry;
218  Oid dboid = (shared ? InvalidOid : MyDatabaseId);
219  TimestampTz ts;
220 
221  if (!pgstat_track_counts)
222  return;
223 
224  /* Store the data in the table's hash table entry. */
225  ts = GetCurrentTimestamp();
226 
227  /* block acquiring lock for the same reason as pgstat_report_autovac() */
229  dboid, tableoid, false);
230 
231  shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
232  tabentry = &shtabentry->stats;
233 
234  tabentry->live_tuples = livetuples;
235  tabentry->dead_tuples = deadtuples;
236 
237  /*
238  * It is quite possible that a non-aggressive VACUUM ended up skipping
239  * various pages, however, we'll zero the insert counter here regardless.
240  * It's currently used only to track when we need to perform an "insert"
241  * autovacuum, which are mainly intended to freeze newly inserted tuples.
242  * Zeroing this may just mean we'll not try to vacuum the table again
243  * until enough tuples have been inserted to trigger another insert
244  * autovacuum. An anti-wraparound autovacuum will catch any persistent
245  * stragglers.
246  */
247  tabentry->ins_since_vacuum = 0;
248 
250  {
251  tabentry->last_autovacuum_time = ts;
252  tabentry->autovacuum_count++;
253  }
254  else
255  {
256  tabentry->last_vacuum_time = ts;
257  tabentry->vacuum_count++;
258  }
259 
260  pgstat_unlock_entry(entry_ref);
261 
262  /*
263  * Flush IO statistics now. pgstat_report_stat() will flush IO stats,
264  * however this will not be called until after an entire autovacuum cycle
265  * is done -- which will likely vacuum many relations -- or until the
266  * VACUUM command has processed all tables and committed.
267  */
268  pgstat_flush_io(false);
269 }
PgStat_Counter vacuum_count
Definition: pgstat.h:420
TimestampTz last_autovacuum_time
Definition: pgstat.h:421
PgStat_Counter autovacuum_count
Definition: pgstat.h:422
TimestampTz last_vacuum_time
Definition: pgstat.h:419

References PgStat_StatTabEntry::autovacuum_count, PgStat_StatTabEntry::dead_tuples, GetCurrentTimestamp(), if(), PgStat_StatTabEntry::ins_since_vacuum, InvalidOid, IsAutoVacuumWorkerProcess(), PgStat_StatTabEntry::last_autovacuum_time, PgStat_StatTabEntry::last_vacuum_time, PgStat_StatTabEntry::live_tuples, MyDatabaseId, pgstat_flush_io(), pgstat_get_entry_ref_locked(), PGSTAT_KIND_RELATION, pgstat_track_counts, pgstat_unlock_entry(), PgStat_EntryRef::shared_stats, PgStatShared_Relation::stats, and PgStat_StatTabEntry::vacuum_count.

Referenced by heap_vacuum_rel().

◆ pgstat_twophase_postabort()

void pgstat_twophase_postabort ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

◆ pgstat_twophase_postcommit()

void pgstat_twophase_postcommit ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 702 of file pgstat_relation.c.

704 {
705  TwoPhasePgStatRecord *rec = (TwoPhasePgStatRecord *) recdata;
706  PgStat_TableStatus *pgstat_info;
707 
708  /* Find or create a tabstat entry for the rel */
709  pgstat_info = pgstat_prep_relation_pending(rec->id, rec->shared);
710 
711  /* Same math as in AtEOXact_PgStat, commit case */
712  pgstat_info->counts.tuples_inserted += rec->tuples_inserted;
713  pgstat_info->counts.tuples_updated += rec->tuples_updated;
714  pgstat_info->counts.tuples_deleted += rec->tuples_deleted;
715  pgstat_info->counts.truncdropped = rec->truncdropped;
716  if (rec->truncdropped)
717  {
718  /* forget live/dead stats seen by backend thus far */
719  pgstat_info->counts.delta_live_tuples = 0;
720  pgstat_info->counts.delta_dead_tuples = 0;
721  }
722  pgstat_info->counts.delta_live_tuples +=
723  rec->tuples_inserted - rec->tuples_deleted;
724  pgstat_info->counts.delta_dead_tuples +=
725  rec->tuples_updated + rec->tuples_deleted;
726  pgstat_info->counts.changed_tuples +=
727  rec->tuples_inserted + rec->tuples_updated +
728  rec->tuples_deleted;
729 }

References PgStat_TableCounts::changed_tuples, PgStat_TableStatus::counts, PgStat_TableCounts::delta_dead_tuples, PgStat_TableCounts::delta_live_tuples, TwoPhasePgStatRecord::id, pgstat_prep_relation_pending(), TwoPhasePgStatRecord::shared, TwoPhasePgStatRecord::truncdropped, PgStat_TableCounts::truncdropped, TwoPhasePgStatRecord::tuples_deleted, PgStat_TableCounts::tuples_deleted, TwoPhasePgStatRecord::tuples_inserted, PgStat_TableCounts::tuples_inserted, TwoPhasePgStatRecord::tuples_updated, and PgStat_TableCounts::tuples_updated.

◆ pgstat_unlink_relation()

void pgstat_unlink_relation ( Relation  rel)

Definition at line 154 of file pgstat_relation.c.

155 {
156  /* remove the link to stats info if any */
157  if (rel->pgstat_info == NULL)
158  return;
159 
160  /* link sanity check */
161  Assert(rel->pgstat_info->relation == rel);
162  rel->pgstat_info->relation = NULL;
163  rel->pgstat_info = NULL;
164 }

References Assert(), RelationData::pgstat_info, and PgStat_TableStatus::relation.

Referenced by pgstat_init_relation(), pgstat_relation_delete_pending_cb(), and RelationDestroyRelation().

◆ pgstat_update_heap_dead_tuples()

void pgstat_update_heap_dead_tuples ( Relation  rel,
int  delta 
)

Definition at line 440 of file pgstat_relation.c.

441 {
443  {
444  PgStat_TableStatus *pgstat_info = rel->pgstat_info;
445 
446  pgstat_info->counts.delta_dead_tuples -= delta;
447  }
448 }

References PgStat_TableStatus::counts, PgStat_TableCounts::delta_dead_tuples, RelationData::pgstat_info, and pgstat_should_count_relation.

Referenced by heap_page_prune_opt().

◆ PostPrepare_PgStat_Relations()

void PostPrepare_PgStat_Relations ( PgStat_SubXactStatus xact_state)

Definition at line 683 of file pgstat_relation.c.

684 {
686 
687  for (trans = xact_state->first; trans != NULL; trans = trans->next)
688  {
689  PgStat_TableStatus *tabstat;
690 
691  tabstat = trans->parent;
692  tabstat->trans = NULL;
693  }
694 }

References PgStat_SubXactStatus::first, PgStat_TableStatus::trans, and trans.

Referenced by PostPrepare_PgStat().

◆ restore_truncdrop_counters()

static void restore_truncdrop_counters ( PgStat_TableXactStatus trans)
static

Definition at line 947 of file pgstat_relation.c.

948 {
949  if (trans->truncdropped)
950  {
951  trans->tuples_inserted = trans->inserted_pre_truncdrop;
952  trans->tuples_updated = trans->updated_pre_truncdrop;
953  trans->tuples_deleted = trans->deleted_pre_truncdrop;
954  }
955 }

References trans.

Referenced by AtEOSubXact_PgStat_Relations(), and AtEOXact_PgStat_Relations().

◆ save_truncdrop_counters()

static void save_truncdrop_counters ( PgStat_TableXactStatus trans,
bool  is_drop 
)
static

Definition at line 932 of file pgstat_relation.c.

933 {
934  if (!trans->truncdropped || is_drop)
935  {
936  trans->inserted_pre_truncdrop = trans->tuples_inserted;
937  trans->updated_pre_truncdrop = trans->tuples_updated;
938  trans->deleted_pre_truncdrop = trans->tuples_deleted;
939  trans->truncdropped = true;
940  }
941 }

References trans.

Referenced by AtEOSubXact_PgStat_Relations(), pgstat_count_truncate(), and pgstat_drop_relation().