PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pgstat_relation.c File Reference
#include "postgres.h"
#include "access/twophase_rmgr.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"
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 (Relation rel, PgStat_Counter livetuples, PgStat_Counter deadtuples, TimestampTz starttime)
 
void pgstat_report_analyze (Relation rel, PgStat_Counter livetuples, PgStat_Counter deadtuples, bool resetcounter, TimestampTz starttime)
 
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, bool *may_free)
 
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 (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
void pgstat_twophase_postabort (FullTransactionId fxid, 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)
 
void pgstat_relation_reset_timestamp_cb (PgStatShared_Common *header, TimestampTz ts)
 

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 944 of file pgstat_relation.c.

945{
946 PgStat_SubXactStatus *xact_state;
948
949 /*
950 * If this is the first rel to be modified at the current nest level, we
951 * first have to push a transaction stack entry.
952 */
953 xact_state = pgstat_get_xact_stack_level(nest_level);
954
955 /* Now make a per-table stack entry */
958 sizeof(PgStat_TableXactStatus));
959 trans->nest_level = nest_level;
960 trans->upper = pgstat_info->trans;
961 trans->parent = pgstat_info;
962 trans->next = xact_state->first;
963 xact_state->first = trans;
964 pgstat_info->trans = trans;
965}
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1266
MemoryContext TopTransactionContext
Definition mcxt.c:171
PgStat_SubXactStatus * pgstat_get_xact_stack_level(int nest_level)
PgStat_TableXactStatus * first
struct PgStat_TableXactStatus * trans
Definition pgstat.h:184
PgStat_TableStatus * parent
Definition pgstat.h:207
static zic_t trans[TZ_MAX_LEAPS]
Definition zic.c:405

References PgStat_SubXactStatus::first, MemoryContextAllocZero(), PgStat_TableXactStatus::parent, 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 610 of file pgstat_relation.c.

611{
614
615 for (trans = xact_state->first; trans != NULL; trans = next_trans)
616 {
618
619 next_trans = trans->next;
620 Assert(trans->nest_level == nestDepth);
621 tabstat = trans->parent;
622 Assert(tabstat->trans == trans);
623
624 if (isCommit)
625 {
626 if (trans->upper && trans->upper->nest_level == nestDepth - 1)
627 {
628 if (trans->truncdropped)
629 {
630 /* propagate the truncate/drop status one level up */
631 save_truncdrop_counters(trans->upper, false);
632 /* replace upper xact stats with ours */
633 trans->upper->tuples_inserted = trans->tuples_inserted;
634 trans->upper->tuples_updated = trans->tuples_updated;
635 trans->upper->tuples_deleted = trans->tuples_deleted;
636 }
637 else
638 {
639 trans->upper->tuples_inserted += trans->tuples_inserted;
640 trans->upper->tuples_updated += trans->tuples_updated;
641 trans->upper->tuples_deleted += trans->tuples_deleted;
642 }
643 tabstat->trans = trans->upper;
644 pfree(trans);
645 }
646 else
647 {
648 /*
649 * When there isn't an immediate parent state, we can just
650 * reuse the record instead of going through a palloc/pfree
651 * pushup (this works since it's all in TopTransactionContext
652 * anyway). We have to re-link it into the parent level,
653 * though, and that might mean pushing a new entry into the
654 * pgStatXactStack.
655 */
657
659 trans->next = upper_xact_state->first;
660 upper_xact_state->first = trans;
661 trans->nest_level = nestDepth - 1;
662 }
663 }
664 else
665 {
666 /*
667 * On abort, update top-level tabstat counts, then forget the
668 * subtransaction
669 */
670
671 /* first restore values obliterated by truncate/drop */
673 /* count attempted actions regardless of commit/abort */
674 tabstat->counts.tuples_inserted += trans->tuples_inserted;
675 tabstat->counts.tuples_updated += trans->tuples_updated;
676 tabstat->counts.tuples_deleted += trans->tuples_deleted;
677 /* inserted tuples are dead, deleted tuples are unaffected */
678 tabstat->counts.delta_dead_tuples +=
679 trans->tuples_inserted + trans->tuples_updated;
680 tabstat->trans = trans->upper;
681 pfree(trans);
682 }
683 }
684}
#define Assert(condition)
Definition c.h:943
void pfree(void *pointer)
Definition mcxt.c:1616
static void save_truncdrop_counters(PgStat_TableXactStatus *trans, bool is_drop)
static void restore_truncdrop_counters(PgStat_TableXactStatus *trans)
static int fb(int x)

References Assert, fb(), PgStat_SubXactStatus::first, pfree(), pgstat_get_xact_stack_level(), restore_truncdrop_counters(), save_truncdrop_counters(), and trans.

Referenced by AtEOSubXact_PgStat().

◆ AtEOXact_PgStat_Relations()

void AtEOXact_PgStat_Relations ( PgStat_SubXactStatus xact_state,
bool  isCommit 
)

Definition at line 552 of file pgstat_relation.c.

553{
555
556 for (trans = xact_state->first; trans != NULL; trans = trans->next)
557 {
559
560 Assert(trans->nest_level == 1);
561 Assert(trans->upper == NULL);
562 tabstat = trans->parent;
563 Assert(tabstat->trans == trans);
564 /* restore pre-truncate/drop stats (if any) in case of aborted xact */
565 if (!isCommit)
567 /* count attempted actions regardless of commit/abort */
568 tabstat->counts.tuples_inserted += trans->tuples_inserted;
569 tabstat->counts.tuples_updated += trans->tuples_updated;
570 tabstat->counts.tuples_deleted += trans->tuples_deleted;
571 if (isCommit)
572 {
573 tabstat->counts.truncdropped = trans->truncdropped;
574 if (trans->truncdropped)
575 {
576 /* forget live/dead stats seen by backend thus far */
577 tabstat->counts.delta_live_tuples = 0;
578 tabstat->counts.delta_dead_tuples = 0;
579 }
580 /* insert adds a live tuple, delete removes one */
581 tabstat->counts.delta_live_tuples +=
582 trans->tuples_inserted - trans->tuples_deleted;
583 /* update and delete each create a dead tuple */
584 tabstat->counts.delta_dead_tuples +=
585 trans->tuples_updated + trans->tuples_deleted;
586 /* insert, update, delete each count as one change event */
587 tabstat->counts.changed_tuples +=
588 trans->tuples_inserted + trans->tuples_updated +
589 trans->tuples_deleted;
590 }
591 else
592 {
593 /* inserted tuples are dead, deleted tuples are unaffected */
594 tabstat->counts.delta_dead_tuples +=
595 trans->tuples_inserted + trans->tuples_updated;
596 /* an aborted xact generates no changed_tuple events */
597 }
598 tabstat->trans = NULL;
599 }
600}

References Assert, fb(), PgStat_SubXactStatus::first, restore_truncdrop_counters(), and trans.

Referenced by AtEOXact_PgStat().

◆ AtPrepare_PgStat_Relations()

void AtPrepare_PgStat_Relations ( PgStat_SubXactStatus xact_state)

Definition at line 691 of file pgstat_relation.c.

692{
694
695 for (trans = xact_state->first; trans != NULL; trans = trans->next)
696 {
699
700 Assert(trans->nest_level == 1);
701 Assert(trans->upper == NULL);
702 tabstat = trans->parent;
703 Assert(tabstat->trans == trans);
704
705 record.tuples_inserted = trans->tuples_inserted;
706 record.tuples_updated = trans->tuples_updated;
707 record.tuples_deleted = trans->tuples_deleted;
708 record.inserted_pre_truncdrop = trans->inserted_pre_truncdrop;
709 record.updated_pre_truncdrop = trans->updated_pre_truncdrop;
710 record.deleted_pre_truncdrop = trans->deleted_pre_truncdrop;
711 record.id = tabstat->id;
712 record.shared = tabstat->shared;
713 record.truncdropped = trans->truncdropped;
714
716 &record, sizeof(TwoPhasePgStatRecord));
717 }
718}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:249
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:1277
#define TWOPHASE_RM_PGSTAT_ID

References Assert, TwoPhasePgStatRecord::deleted_pre_truncdrop, fb(), 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 971 of file pgstat_relation.c.

972{
973 int nest_level = GetCurrentTransactionNestLevel();
974
975 if (pgstat_info->trans == NULL ||
976 pgstat_info->trans->nest_level != nest_level)
977 add_tabstat_xact_level(pgstat_info, nest_level);
978}
static void add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
int GetCurrentTransactionNestLevel(void)
Definition xact.c:931

References add_tabstat_xact_level(), fb(), 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 502 of file pgstat_relation.c.

503{
504 PgStat_EntryRef *entry_ref;
508
510 if (!entry_ref)
511 {
513 if (!entry_ref)
514 return tablestatus;
515 }
516
517 tabentry = (PgStat_TableStatus *) entry_ref->pending;
520
521 /*
522 * Reset tablestatus->trans in the copy of PgStat_TableStatus as it may
523 * point to a shared memory area. Its data is saved below, so removing it
524 * does not matter.
525 */
526 tablestatus->trans = NULL;
527
528 /*
529 * Live subtransaction counts are not included yet. This is not a hot
530 * code path so reconcile tuples_inserted, tuples_updated and
531 * tuples_deleted even if the caller may not be interested in this data.
532 */
533 for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
534 {
535 tablestatus->counts.tuples_inserted += trans->tuples_inserted;
536 tablestatus->counts.tuples_updated += trans->tuples_updated;
537 tablestatus->counts.tuples_deleted += trans->tuples_deleted;
538 }
539
540 return tablestatus;
541}
#define palloc_object(type)
Definition fe_memutils.h:74
Oid MyDatabaseId
Definition globals.c:96
PgStat_EntryRef * pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
Definition pgstat.c:1347
#define PGSTAT_KIND_RELATION
Definition pgstat_kind.h:28
#define InvalidOid

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

◆ pgstat_assoc_relation()

void pgstat_assoc_relation ( Relation  rel)

Definition at line 132 of file pgstat_relation.c.

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

References Assert, fb(), 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 57 of file pgstat_relation.c.

58{
62
65 NULL);
66 if (!srcstats)
67 return;
68
70 dst->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
72 false);
73
75 dstshstats->stats = *srcstats;
76
78}
#define false
PgStat_StatTabEntry * pgstat_fetch_stat_tabentry_ext(bool shared, Oid reloid, bool *may_free)
void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
PgStat_EntryRef * pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, uint64 objid, bool nowait)
PgStatShared_Common * shared_stats

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

Referenced by index_concurrently_swap().

◆ pgstat_count_heap_delete()

void pgstat_count_heap_delete ( Relation  rel)

Definition at line 415 of file pgstat_relation.c.

416{
418 {
419 PgStat_TableStatus *pgstat_info = rel->pgstat_info;
420
421 ensure_tabstat_xact_level(pgstat_info);
422 pgstat_info->trans->tuples_deleted++;
423 }
424}
#define pgstat_should_count_relation(rel)
Definition pgstat.h:711
static void ensure_tabstat_xact_level(PgStat_TableStatus *pgstat_info)
PgStat_Counter tuples_deleted
Definition pgstat.h:197

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 
)

◆ pgstat_count_heap_update()

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

Definition at line 389 of file pgstat_relation.c.

390{
391 Assert(!(hot && newpage));
392
394 {
395 PgStat_TableStatus *pgstat_info = rel->pgstat_info;
396
397 ensure_tabstat_xact_level(pgstat_info);
398 pgstat_info->trans->tuples_updated++;
399
400 /*
401 * tuples_hot_updated and tuples_newpage_updated counters are
402 * nontransactional, so just advance them
403 */
404 if (hot)
405 pgstat_info->counts.tuples_hot_updated++;
406 else if (newpage)
407 pgstat_info->counts.tuples_newpage_updated++;
408 }
409}
PgStat_Counter tuples_hot_updated
Definition pgstat.h:153
PgStat_Counter tuples_newpage_updated
Definition pgstat.h:154
PgStat_TableCounts counts
Definition pgstat.h:185
PgStat_Counter tuples_updated
Definition pgstat.h:196

References Assert, PgStat_TableStatus::counts, ensure_tabstat_xact_level(), fb(), 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()

◆ pgstat_create_relation()

void pgstat_create_relation ( Relation  rel)

Definition at line 169 of file pgstat_relation.c.

170{
172 rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
173 RelationGetRelid(rel));
174}
void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, uint64 objid)

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 180 of file pgstat_relation.c.

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

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 470 of file pgstat_relation.c.

471{
473}
bool IsSharedRelation(Oid relationId)
Definition catalog.c:304

References fb(), IsSharedRelation(), and pgstat_fetch_stat_tabentry_ext().

◆ pgstat_fetch_stat_tabentry_ext()

PgStat_StatTabEntry * pgstat_fetch_stat_tabentry_ext ( bool  shared,
Oid  reloid,
bool may_free 
)

Definition at line 481 of file pgstat_relation.c.

482{
483 Oid dboid = (shared ? InvalidOid : MyDatabaseId);
484
485 return (PgStat_StatTabEntry *)
487}
void * pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid, bool *may_free)
Definition pgstat.c:962
unsigned int Oid

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

Referenced by pgstat_copy_relation_stats(), pgstat_fetch_stat_tabentry(), and relation_needs_vacanalyze().

◆ pgstat_init_relation()

void pgstat_init_relation ( Relation  rel)

Definition at line 92 of file pgstat_relation.c.

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

References fb(), 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 925 of file pgstat_relation.c.

926{
927 PgStat_EntryRef *entry_ref;
928 PgStat_TableStatus *pending;
929
931 isshared ? InvalidOid : MyDatabaseId,
932 rel_id, NULL);
933 pending = entry_ref->pending;
934 pending->id = rel_id;
935 pending->shared = isshared;
936
937 return pending;
938}
PgStat_EntryRef * pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid, bool *created_entry)
Definition pgstat.c:1309

References fb(), 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 906 of file pgstat_relation.c.

907{
908 PgStat_TableStatus *pending = (PgStat_TableStatus *) entry_ref->pending;
909
910 if (pending->relation)
911 pgstat_unlink_relation(pending->relation);
912}

References 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 817 of file pgstat_relation.c.

818{
819 Oid dboid;
820 PgStat_TableStatus *lstats; /* pending stats entry */
822 PgStat_StatTabEntry *tabentry; /* table entry of shared stats */
823 PgStat_StatDBEntry *dbentry; /* pending database entry */
824
825 dboid = entry_ref->shared_entry->key.dboid;
826 lstats = (PgStat_TableStatus *) entry_ref->pending;
828
829 /*
830 * Ignore entries that didn't accumulate any actual counts, such as
831 * indexes that were opened by the planner but not used.
832 */
833 if (pg_memory_is_all_zeros(&lstats->counts,
834 sizeof(struct PgStat_TableCounts)))
835 return true;
836
837 if (!pgstat_lock_entry(entry_ref, nowait))
838 return false;
839
840 /* add the values to the shared entry. */
841 tabentry = &shtabstats->stats;
842
843 tabentry->numscans += lstats->counts.numscans;
844 if (lstats->counts.numscans)
845 {
847
848 if (t > tabentry->lastscan)
849 tabentry->lastscan = t;
850 }
851 tabentry->tuples_returned += lstats->counts.tuples_returned;
852 tabentry->tuples_fetched += lstats->counts.tuples_fetched;
853 tabentry->tuples_inserted += lstats->counts.tuples_inserted;
854 tabentry->tuples_updated += lstats->counts.tuples_updated;
855 tabentry->tuples_deleted += lstats->counts.tuples_deleted;
856 tabentry->tuples_hot_updated += lstats->counts.tuples_hot_updated;
857 tabentry->tuples_newpage_updated += lstats->counts.tuples_newpage_updated;
858
859 /*
860 * If table was truncated/dropped, first reset the live/dead counters.
861 */
862 if (lstats->counts.truncdropped)
863 {
864 tabentry->live_tuples = 0;
865 tabentry->dead_tuples = 0;
866 tabentry->ins_since_vacuum = 0;
867 }
868
869 tabentry->live_tuples += lstats->counts.delta_live_tuples;
870 tabentry->dead_tuples += lstats->counts.delta_dead_tuples;
871 tabentry->mod_since_analyze += lstats->counts.changed_tuples;
872
873 /*
874 * Using tuples_inserted to update ins_since_vacuum does mean that we'll
875 * track aborted inserts too. This isn't ideal, but otherwise probably
876 * not worth adding an extra field for. It may just amount to autovacuums
877 * triggering for inserts more often than they maybe should, which is
878 * probably not going to be common enough to be too concerned about here.
879 */
880 tabentry->ins_since_vacuum += lstats->counts.tuples_inserted;
881
882 tabentry->blocks_fetched += lstats->counts.blocks_fetched;
883 tabentry->blocks_hit += lstats->counts.blocks_hit;
884
885 /* Clamp live_tuples in case of negative delta_live_tuples */
886 tabentry->live_tuples = Max(tabentry->live_tuples, 0);
887 /* Likewise for dead_tuples */
888 tabentry->dead_tuples = Max(tabentry->dead_tuples, 0);
889
890 pgstat_unlock_entry(entry_ref);
891
892 /* The entry was successfully flushed, add the same to database stats */
894 dbentry->tuples_returned += lstats->counts.tuples_returned;
895 dbentry->tuples_fetched += lstats->counts.tuples_fetched;
896 dbentry->tuples_inserted += lstats->counts.tuples_inserted;
897 dbentry->tuples_updated += lstats->counts.tuples_updated;
898 dbentry->tuples_deleted += lstats->counts.tuples_deleted;
899 dbentry->blocks_fetched += lstats->counts.blocks_fetched;
900 dbentry->blocks_hit += lstats->counts.blocks_hit;
901
902 return true;
903}
#define Max(x, y)
Definition c.h:1085
int64 TimestampTz
Definition timestamp.h:39
static bool pg_memory_is_all_zeros(const void *ptr, size_t len)
Definition memutils.h:219
PgStat_StatDBEntry * pgstat_prep_database_pending(Oid dboid)
bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait)
PgStatShared_HashEntry * shared_entry
TimestampTz GetCurrentTransactionStopTimestamp(void)
Definition xact.c:893

References PgStat_HashKey::dboid, fb(), GetCurrentTransactionStopTimestamp(), PgStatShared_HashEntry::key, Max, PgStat_EntryRef::pending, pg_memory_is_all_zeros(), pgstat_lock_entry(), pgstat_prep_database_pending(), pgstat_unlock_entry(), PgStat_EntryRef::shared_entry, and PgStat_EntryRef::shared_stats.

◆ pgstat_relation_reset_timestamp_cb()

void pgstat_relation_reset_timestamp_cb ( PgStatShared_Common header,
TimestampTz  ts 
)

Definition at line 915 of file pgstat_relation.c.

916{
917 ((PgStatShared_Relation *) header)->stats.stat_reset_time = ts;
918}

◆ pgstat_report_analyze()

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

Definition at line 282 of file pgstat_relation.c.

285{
286 PgStat_EntryRef *entry_ref;
289 Oid dboid = (rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId);
290 TimestampTz ts;
292
294 return;
295
296 /*
297 * Unlike VACUUM, ANALYZE might be running inside a transaction that has
298 * already inserted and/or deleted rows in the target table. ANALYZE will
299 * have counted such rows as live or dead respectively. Because we will
300 * report our counts of such rows at transaction end, we should subtract
301 * off these counts from the update we're making now, else they'll be
302 * double-counted after commit. (This approach also ensures that the
303 * shared stats entry ends up with the right numbers if we abort instead
304 * of committing.)
305 *
306 * Waste no time on partitioned tables, though.
307 */
309 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
310 {
312
313 for (trans = rel->pgstat_info->trans; trans; trans = trans->upper)
314 {
315 livetuples -= trans->tuples_inserted - trans->tuples_deleted;
316 deadtuples -= trans->tuples_updated + trans->tuples_deleted;
317 }
318 /* count stuff inserted by already-aborted subxacts, too */
320 /* Since ANALYZE's counts are estimates, we could have underflowed */
323 }
324
325 /* Store the data in the table's hash table entry. */
326 ts = GetCurrentTimestamp();
328
329 /* block acquiring lock for the same reason as pgstat_report_autovac() */
331 RelationGetRelid(rel),
332 false);
333 /* can't get dropped while accessed */
334 Assert(entry_ref != NULL && entry_ref->shared_stats != NULL);
335
337 tabentry = &shtabentry->stats;
338
339 tabentry->live_tuples = livetuples;
340 tabentry->dead_tuples = deadtuples;
341
342 /*
343 * If commanded, reset mod_since_analyze to zero. This forgets any
344 * changes that were committed while the ANALYZE was in progress, but we
345 * have no good way to estimate how many of those there were.
346 */
347 if (resetcounter)
348 tabentry->mod_since_analyze = 0;
349
351 {
352 tabentry->last_autoanalyze_time = ts;
353 tabentry->autoanalyze_count++;
354 tabentry->total_autoanalyze_time += elapsedtime;
355 }
356 else
357 {
358 tabentry->last_analyze_time = ts;
359 tabentry->analyze_count++;
360 tabentry->total_analyze_time += elapsedtime;
361 }
362
363 pgstat_unlock_entry(entry_ref);
364
365 /* see pgstat_report_vacuum() */
366 pgstat_flush_io(false);
368}
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition timestamp.c:1751
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1639
#define AmAutoVacuumWorkerProcess()
Definition miscadmin.h:398
int64 PgStat_Counter
Definition pgstat.h:71
bool pgstat_flush_backend(bool nowait, uint32 flags)
#define PGSTAT_BACKEND_FLUSH_IO
void pgstat_flush_io(bool nowait)
Definition pgstat_io.c:175
PgStat_Counter delta_dead_tuples
Definition pgstat.h:158

References AmAutoVacuumWorkerProcess, Assert, PgStat_TableStatus::counts, PgStat_TableCounts::delta_dead_tuples, fb(), GetCurrentTimestamp(), InvalidOid, Max, MyDatabaseId, PGSTAT_BACKEND_FLUSH_IO, pgstat_flush_backend(), 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, TimestampDifferenceMilliseconds(), PgStat_TableStatus::trans, trans, and PgStat_TableXactStatus::tuples_inserted.

Referenced by do_analyze_rel().

◆ pgstat_report_vacuum()

void pgstat_report_vacuum ( Relation  rel,
PgStat_Counter  livetuples,
PgStat_Counter  deadtuples,
TimestampTz  starttime 
)

Definition at line 211 of file pgstat_relation.c.

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

References AmAutoVacuumWorkerProcess, fb(), GetCurrentTimestamp(), InvalidOid, MyDatabaseId, PGSTAT_BACKEND_FLUSH_IO, pgstat_flush_backend(), pgstat_flush_io(), pgstat_get_entry_ref_locked(), PGSTAT_KIND_RELATION, pgstat_track_counts, pgstat_unlock_entry(), RelationData::rd_rel, RelationGetRelid, PgStat_EntryRef::shared_stats, and TimestampDifferenceMilliseconds().

Referenced by heap_vacuum_rel().

◆ pgstat_twophase_postabort()

void pgstat_twophase_postabort ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)

Definition at line 784 of file pgstat_relation.c.

786{
788 PgStat_TableStatus *pgstat_info;
789
790 /* Find or create a tabstat entry for the rel */
791 pgstat_info = pgstat_prep_relation_pending(rec->id, rec->shared);
792
793 /* Same math as in AtEOXact_PgStat, abort case */
794 if (rec->truncdropped)
795 {
799 }
800 pgstat_info->counts.tuples_inserted += rec->tuples_inserted;
801 pgstat_info->counts.tuples_updated += rec->tuples_updated;
802 pgstat_info->counts.tuples_deleted += rec->tuples_deleted;
803 pgstat_info->counts.delta_dead_tuples +=
805}
PgStat_Counter tuples_inserted
Definition pgstat.h:150
PgStat_Counter tuples_updated
Definition pgstat.h:151
PgStat_Counter tuples_deleted
Definition pgstat.h:152

References PgStat_TableStatus::counts, TwoPhasePgStatRecord::deleted_pre_truncdrop, PgStat_TableCounts::delta_dead_tuples, fb(), TwoPhasePgStatRecord::id, TwoPhasePgStatRecord::inserted_pre_truncdrop, pgstat_prep_relation_pending(), TwoPhasePgStatRecord::shared, TwoPhasePgStatRecord::truncdropped, TwoPhasePgStatRecord::tuples_deleted, PgStat_TableCounts::tuples_deleted, TwoPhasePgStatRecord::tuples_inserted, PgStat_TableCounts::tuples_inserted, TwoPhasePgStatRecord::tuples_updated, PgStat_TableCounts::tuples_updated, and TwoPhasePgStatRecord::updated_pre_truncdrop.

◆ pgstat_twophase_postcommit()

void pgstat_twophase_postcommit ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)

Definition at line 748 of file pgstat_relation.c.

750{
752 PgStat_TableStatus *pgstat_info;
753
754 /* Find or create a tabstat entry for the rel */
755 pgstat_info = pgstat_prep_relation_pending(rec->id, rec->shared);
756
757 /* Same math as in AtEOXact_PgStat, commit case */
758 pgstat_info->counts.tuples_inserted += rec->tuples_inserted;
759 pgstat_info->counts.tuples_updated += rec->tuples_updated;
760 pgstat_info->counts.tuples_deleted += rec->tuples_deleted;
761 pgstat_info->counts.truncdropped = rec->truncdropped;
762 if (rec->truncdropped)
763 {
764 /* forget live/dead stats seen by backend thus far */
765 pgstat_info->counts.delta_live_tuples = 0;
766 pgstat_info->counts.delta_dead_tuples = 0;
767 }
768 pgstat_info->counts.delta_live_tuples +=
770 pgstat_info->counts.delta_dead_tuples +=
771 rec->tuples_updated + rec->tuples_deleted;
772 pgstat_info->counts.changed_tuples +=
773 rec->tuples_inserted + rec->tuples_updated +
774 rec->tuples_deleted;
775}
PgStat_Counter delta_live_tuples
Definition pgstat.h:157
PgStat_Counter changed_tuples
Definition pgstat.h:159

References PgStat_TableCounts::changed_tuples, PgStat_TableStatus::counts, PgStat_TableCounts::delta_dead_tuples, PgStat_TableCounts::delta_live_tuples, fb(), 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 153 of file pgstat_relation.c.

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

References Assert, fb(), 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 453 of file pgstat_relation.c.

454{
456 {
457 PgStat_TableStatus *pgstat_info = rel->pgstat_info;
458
459 pgstat_info->counts.delta_dead_tuples -= delta;
460 }
461}

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 729 of file pgstat_relation.c.

730{
732
733 for (trans = xact_state->first; trans != NULL; trans = trans->next)
734 {
736
737 tabstat = trans->parent;
738 tabstat->trans = NULL;
739 }
740}

References fb(), 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 1005 of file pgstat_relation.c.

1006{
1007 if (trans->truncdropped)
1008 {
1009 trans->tuples_inserted = trans->inserted_pre_truncdrop;
1010 trans->tuples_updated = trans->updated_pre_truncdrop;
1011 trans->tuples_deleted = trans->deleted_pre_truncdrop;
1012 }
1013}

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 990 of file pgstat_relation.c.

991{
992 if (!trans->truncdropped || is_drop)
993 {
994 trans->inserted_pre_truncdrop = trans->tuples_inserted;
995 trans->updated_pre_truncdrop = trans->tuples_updated;
996 trans->deleted_pre_truncdrop = trans->tuples_deleted;
997 trans->truncdropped = true;
998 }
999}

References fb(), and trans.

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