mirror of
https://github.com/postgres/postgres.git
synced 2025-12-06 00:02:13 +03:00
Revise pgstat's tracking of tuple changes to improve the reliability of
decisions about when to auto-analyze. The previous code depended on n_live_tuples + n_dead_tuples - last_anl_tuples, where all three of these numbers could be bad estimates from ANALYZE itself. Even worse, in the presence of a steady flow of HOT updates and matching HOT-tuple reclamations, auto-analyze might never trigger at all, even if all three numbers are exactly right, because n_dead_tuples could hold steady. To fix, replace last_anl_tuples with an accurately tracked count of the total number of committed tuple inserts + updates + deletes since the last ANALYZE on the table. This can still be compared to the same threshold as before, but it's much more trustworthy than the old computation. Tracking this requires one more intra-transaction counter per modified table within backends, but no additional memory space in the stats collector. There probably isn't any measurable speed difference; if anything it might be a bit faster than before, since I was able to eliminate some per-tuple arithmetic operations in favor of adding sums once per (sub)transaction. Also, simplify the logic around pgstat vacuum and analyze reporting messages by not trying to fold VACUUM ANALYZE into a single pgstat message. The original thought behind this patch was to allow scheduling of analyzes on parent tables by artificially inflating their changes_since_analyze count. I've left that for a separate patch since this change seems to stand on its own merit.
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* Copyright (c) 2001-2009, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.194 2009/12/27 19:40:07 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.195 2009/12/30 20:32:14 tgl Exp $
|
||||
* ----------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
@@ -195,6 +195,7 @@ static int pgStatXactRollback = 0;
|
||||
typedef struct TwoPhasePgStatRecord
|
||||
{
|
||||
PgStat_Counter tuples_inserted; /* tuples inserted in xact */
|
||||
PgStat_Counter tuples_updated; /* tuples updated in xact */
|
||||
PgStat_Counter tuples_deleted; /* tuples deleted in xact */
|
||||
Oid t_id; /* table's OID */
|
||||
bool t_shared; /* is it a shared catalog? */
|
||||
@@ -1184,8 +1185,8 @@ pgstat_report_autovac(Oid dboid)
|
||||
* ---------
|
||||
*/
|
||||
void
|
||||
pgstat_report_vacuum(Oid tableoid, bool shared, bool scanned_all,
|
||||
bool analyze, PgStat_Counter tuples)
|
||||
pgstat_report_vacuum(Oid tableoid, bool shared, bool adopt_counts,
|
||||
PgStat_Counter tuples)
|
||||
{
|
||||
PgStat_MsgVacuum msg;
|
||||
|
||||
@@ -1195,9 +1196,8 @@ pgstat_report_vacuum(Oid tableoid, bool shared, bool scanned_all,
|
||||
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_VACUUM);
|
||||
msg.m_databaseid = shared ? InvalidOid : MyDatabaseId;
|
||||
msg.m_tableoid = tableoid;
|
||||
msg.m_scanned_all = scanned_all;
|
||||
msg.m_analyze = analyze;
|
||||
msg.m_autovacuum = IsAutoVacuumWorkerProcess(); /* is this autovacuum? */
|
||||
msg.m_adopt_counts = adopt_counts;
|
||||
msg.m_autovacuum = IsAutoVacuumWorkerProcess();
|
||||
msg.m_vacuumtime = GetCurrentTimestamp();
|
||||
msg.m_tuples = tuples;
|
||||
pgstat_send(&msg, sizeof(msg));
|
||||
@@ -1210,8 +1210,8 @@ pgstat_report_vacuum(Oid tableoid, bool shared, bool scanned_all,
|
||||
* --------
|
||||
*/
|
||||
void
|
||||
pgstat_report_analyze(Relation rel, PgStat_Counter livetuples,
|
||||
PgStat_Counter deadtuples)
|
||||
pgstat_report_analyze(Relation rel, bool adopt_counts,
|
||||
PgStat_Counter livetuples, PgStat_Counter deadtuples)
|
||||
{
|
||||
PgStat_MsgAnalyze msg;
|
||||
|
||||
@@ -1235,10 +1235,10 @@ pgstat_report_analyze(Relation rel, PgStat_Counter livetuples,
|
||||
for (trans = rel->pgstat_info->trans; trans; trans = trans->upper)
|
||||
{
|
||||
livetuples -= trans->tuples_inserted - trans->tuples_deleted;
|
||||
deadtuples -= trans->tuples_deleted;
|
||||
deadtuples -= trans->tuples_updated + trans->tuples_deleted;
|
||||
}
|
||||
/* count stuff inserted by already-aborted subxacts, too */
|
||||
deadtuples -= rel->pgstat_info->t_counts.t_new_dead_tuples;
|
||||
deadtuples -= rel->pgstat_info->t_counts.t_delta_dead_tuples;
|
||||
/* Since ANALYZE's counts are estimates, we could have underflowed */
|
||||
livetuples = Max(livetuples, 0);
|
||||
deadtuples = Max(deadtuples, 0);
|
||||
@@ -1247,7 +1247,8 @@ pgstat_report_analyze(Relation rel, PgStat_Counter livetuples,
|
||||
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_ANALYZE);
|
||||
msg.m_databaseid = rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId;
|
||||
msg.m_tableoid = RelationGetRelid(rel);
|
||||
msg.m_autovacuum = IsAutoVacuumWorkerProcess(); /* is this autovacuum? */
|
||||
msg.m_adopt_counts = adopt_counts;
|
||||
msg.m_autovacuum = IsAutoVacuumWorkerProcess();
|
||||
msg.m_analyzetime = GetCurrentTimestamp();
|
||||
msg.m_live_tuples = livetuples;
|
||||
msg.m_dead_tuples = deadtuples;
|
||||
@@ -1559,12 +1560,9 @@ pgstat_count_heap_insert(Relation rel)
|
||||
|
||||
if (pgstat_track_counts && pgstat_info != NULL)
|
||||
{
|
||||
/* We have to log the effect at the proper transactional level */
|
||||
int nest_level = GetCurrentTransactionNestLevel();
|
||||
|
||||
/* t_tuples_inserted is nontransactional, so just advance it */
|
||||
pgstat_info->t_counts.t_tuples_inserted++;
|
||||
|
||||
/* We have to log the transactional effect at the proper level */
|
||||
if (pgstat_info->trans == NULL ||
|
||||
pgstat_info->trans->nest_level != nest_level)
|
||||
add_tabstat_xact_level(pgstat_info, nest_level);
|
||||
@@ -1583,22 +1581,18 @@ pgstat_count_heap_update(Relation rel, bool hot)
|
||||
|
||||
if (pgstat_track_counts && pgstat_info != NULL)
|
||||
{
|
||||
/* We have to log the effect at the proper transactional level */
|
||||
int nest_level = GetCurrentTransactionNestLevel();
|
||||
|
||||
/* t_tuples_updated is nontransactional, so just advance it */
|
||||
pgstat_info->t_counts.t_tuples_updated++;
|
||||
/* ditto for the hot_update counter */
|
||||
if (hot)
|
||||
pgstat_info->t_counts.t_tuples_hot_updated++;
|
||||
|
||||
/* We have to log the transactional effect at the proper level */
|
||||
if (pgstat_info->trans == NULL ||
|
||||
pgstat_info->trans->nest_level != nest_level)
|
||||
add_tabstat_xact_level(pgstat_info, nest_level);
|
||||
|
||||
/* An UPDATE both inserts a new tuple and deletes the old */
|
||||
pgstat_info->trans->tuples_inserted++;
|
||||
pgstat_info->trans->tuples_deleted++;
|
||||
pgstat_info->trans->tuples_updated++;
|
||||
|
||||
/* t_tuples_hot_updated is nontransactional, so just advance it */
|
||||
if (hot)
|
||||
pgstat_info->t_counts.t_tuples_hot_updated++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1612,12 +1606,9 @@ pgstat_count_heap_delete(Relation rel)
|
||||
|
||||
if (pgstat_track_counts && pgstat_info != NULL)
|
||||
{
|
||||
/* We have to log the effect at the proper transactional level */
|
||||
int nest_level = GetCurrentTransactionNestLevel();
|
||||
|
||||
/* t_tuples_deleted is nontransactional, so just advance it */
|
||||
pgstat_info->t_counts.t_tuples_deleted++;
|
||||
|
||||
/* We have to log the transactional effect at the proper level */
|
||||
if (pgstat_info->trans == NULL ||
|
||||
pgstat_info->trans->nest_level != nest_level)
|
||||
add_tabstat_xact_level(pgstat_info, nest_level);
|
||||
@@ -1630,7 +1621,7 @@ pgstat_count_heap_delete(Relation rel)
|
||||
* pgstat_update_heap_dead_tuples - update dead-tuples count
|
||||
*
|
||||
* The semantics of this are that we are reporting the nontransactional
|
||||
* recovery of "delta" dead tuples; so t_new_dead_tuples decreases
|
||||
* recovery of "delta" dead tuples; so t_delta_dead_tuples decreases
|
||||
* rather than increasing, and the change goes straight into the per-table
|
||||
* counter, not into transactional state.
|
||||
*/
|
||||
@@ -1640,7 +1631,7 @@ pgstat_update_heap_dead_tuples(Relation rel, int delta)
|
||||
PgStat_TableStatus *pgstat_info = rel->pgstat_info;
|
||||
|
||||
if (pgstat_track_counts && pgstat_info != NULL)
|
||||
pgstat_info->t_counts.t_new_dead_tuples -= delta;
|
||||
pgstat_info->t_counts.t_delta_dead_tuples -= delta;
|
||||
}
|
||||
|
||||
|
||||
@@ -1684,16 +1675,29 @@ AtEOXact_PgStat(bool isCommit)
|
||||
Assert(trans->upper == NULL);
|
||||
tabstat = trans->parent;
|
||||
Assert(tabstat->trans == trans);
|
||||
/* count attempted actions regardless of commit/abort */
|
||||
tabstat->t_counts.t_tuples_inserted += trans->tuples_inserted;
|
||||
tabstat->t_counts.t_tuples_updated += trans->tuples_updated;
|
||||
tabstat->t_counts.t_tuples_deleted += trans->tuples_deleted;
|
||||
if (isCommit)
|
||||
{
|
||||
tabstat->t_counts.t_new_live_tuples +=
|
||||
/* insert adds a live tuple, delete removes one */
|
||||
tabstat->t_counts.t_delta_live_tuples +=
|
||||
trans->tuples_inserted - trans->tuples_deleted;
|
||||
tabstat->t_counts.t_new_dead_tuples += trans->tuples_deleted;
|
||||
/* update and delete each create a dead tuple */
|
||||
tabstat->t_counts.t_delta_dead_tuples +=
|
||||
trans->tuples_updated + trans->tuples_deleted;
|
||||
/* insert, update, delete each count as one change event */
|
||||
tabstat->t_counts.t_changed_tuples +=
|
||||
trans->tuples_inserted + trans->tuples_updated +
|
||||
trans->tuples_deleted;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* inserted tuples are dead, deleted tuples are unaffected */
|
||||
tabstat->t_counts.t_new_dead_tuples += trans->tuples_inserted;
|
||||
tabstat->t_counts.t_delta_dead_tuples +=
|
||||
trans->tuples_inserted + trans->tuples_updated;
|
||||
/* an aborted xact generates no changed_tuple events */
|
||||
}
|
||||
tabstat->trans = NULL;
|
||||
}
|
||||
@@ -1742,6 +1746,7 @@ AtEOSubXact_PgStat(bool isCommit, int nestDepth)
|
||||
if (trans->upper && trans->upper->nest_level == nestDepth - 1)
|
||||
{
|
||||
trans->upper->tuples_inserted += trans->tuples_inserted;
|
||||
trans->upper->tuples_updated += trans->tuples_updated;
|
||||
trans->upper->tuples_deleted += trans->tuples_deleted;
|
||||
tabstat->trans = trans->upper;
|
||||
pfree(trans);
|
||||
@@ -1767,10 +1772,17 @@ AtEOSubXact_PgStat(bool isCommit, int nestDepth)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* On abort, inserted tuples are dead (and can be bounced out
|
||||
* to the top-level tabstat), deleted tuples are unaffected
|
||||
* On abort, update top-level tabstat counts, then forget
|
||||
* the subtransaction
|
||||
*/
|
||||
tabstat->t_counts.t_new_dead_tuples += trans->tuples_inserted;
|
||||
|
||||
/* count attempted actions regardless of commit/abort */
|
||||
tabstat->t_counts.t_tuples_inserted += trans->tuples_inserted;
|
||||
tabstat->t_counts.t_tuples_updated += trans->tuples_updated;
|
||||
tabstat->t_counts.t_tuples_deleted += trans->tuples_deleted;
|
||||
/* inserted tuples are dead, deleted tuples are unaffected */
|
||||
tabstat->t_counts.t_delta_dead_tuples +=
|
||||
trans->tuples_inserted + trans->tuples_updated;
|
||||
tabstat->trans = trans->upper;
|
||||
pfree(trans);
|
||||
}
|
||||
@@ -1810,6 +1822,7 @@ AtPrepare_PgStat(void)
|
||||
Assert(tabstat->trans == trans);
|
||||
|
||||
record.tuples_inserted = trans->tuples_inserted;
|
||||
record.tuples_updated = trans->tuples_updated;
|
||||
record.tuples_deleted = trans->tuples_deleted;
|
||||
record.t_id = tabstat->t_id;
|
||||
record.t_shared = tabstat->t_shared;
|
||||
@@ -1874,9 +1887,17 @@ pgstat_twophase_postcommit(TransactionId xid, uint16 info,
|
||||
/* Find or create a tabstat entry for the rel */
|
||||
pgstat_info = get_tabstat_entry(rec->t_id, rec->t_shared);
|
||||
|
||||
pgstat_info->t_counts.t_new_live_tuples +=
|
||||
/* Same math as in AtEOXact_PgStat, commit case */
|
||||
pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
|
||||
pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated;
|
||||
pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
|
||||
pgstat_info->t_counts.t_delta_live_tuples +=
|
||||
rec->tuples_inserted - rec->tuples_deleted;
|
||||
pgstat_info->t_counts.t_new_dead_tuples += rec->tuples_deleted;
|
||||
pgstat_info->t_counts.t_delta_dead_tuples +=
|
||||
rec->tuples_updated + rec->tuples_deleted;
|
||||
pgstat_info->t_counts.t_changed_tuples +=
|
||||
rec->tuples_inserted + rec->tuples_updated +
|
||||
rec->tuples_deleted;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1895,8 +1916,12 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info,
|
||||
/* Find or create a tabstat entry for the rel */
|
||||
pgstat_info = get_tabstat_entry(rec->t_id, rec->t_shared);
|
||||
|
||||
/* inserted tuples are dead, deleted tuples are no-ops */
|
||||
pgstat_info->t_counts.t_new_dead_tuples += rec->tuples_inserted;
|
||||
/* Same math as in AtEOXact_PgStat, abort case */
|
||||
pgstat_info->t_counts.t_tuples_inserted += rec->tuples_inserted;
|
||||
pgstat_info->t_counts.t_tuples_updated += rec->tuples_updated;
|
||||
pgstat_info->t_counts.t_tuples_deleted += rec->tuples_deleted;
|
||||
pgstat_info->t_counts.t_delta_dead_tuples +=
|
||||
rec->tuples_inserted + rec->tuples_updated;
|
||||
}
|
||||
|
||||
|
||||
@@ -3045,7 +3070,7 @@ pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry, Oid tableoid, bool create)
|
||||
result->tuples_hot_updated = 0;
|
||||
result->n_live_tuples = 0;
|
||||
result->n_dead_tuples = 0;
|
||||
result->last_anl_tuples = 0;
|
||||
result->changes_since_analyze = 0;
|
||||
result->blocks_fetched = 0;
|
||||
result->blocks_hit = 0;
|
||||
|
||||
@@ -3634,7 +3659,6 @@ pgstat_recv_inquiry(PgStat_MsgInquiry *msg, int len)
|
||||
static void
|
||||
pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
|
||||
{
|
||||
PgStat_TableEntry *tabmsg = &(msg->m_entry[0]);
|
||||
PgStat_StatDBEntry *dbentry;
|
||||
PgStat_StatTabEntry *tabentry;
|
||||
int i;
|
||||
@@ -3653,8 +3677,10 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
|
||||
*/
|
||||
for (i = 0; i < msg->m_nentries; i++)
|
||||
{
|
||||
PgStat_TableEntry *tabmsg = &(msg->m_entry[i]);
|
||||
|
||||
tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables,
|
||||
(void *) &(tabmsg[i].t_id),
|
||||
(void *) &(tabmsg->t_id),
|
||||
HASH_ENTER, &found);
|
||||
|
||||
if (!found)
|
||||
@@ -3663,18 +3689,18 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
|
||||
* If it's a new table entry, initialize counters to the values we
|
||||
* just got.
|
||||
*/
|
||||
tabentry->numscans = tabmsg[i].t_counts.t_numscans;
|
||||
tabentry->tuples_returned = tabmsg[i].t_counts.t_tuples_returned;
|
||||
tabentry->tuples_fetched = tabmsg[i].t_counts.t_tuples_fetched;
|
||||
tabentry->tuples_inserted = tabmsg[i].t_counts.t_tuples_inserted;
|
||||
tabentry->tuples_updated = tabmsg[i].t_counts.t_tuples_updated;
|
||||
tabentry->tuples_deleted = tabmsg[i].t_counts.t_tuples_deleted;
|
||||
tabentry->tuples_hot_updated = tabmsg[i].t_counts.t_tuples_hot_updated;
|
||||
tabentry->n_live_tuples = tabmsg[i].t_counts.t_new_live_tuples;
|
||||
tabentry->n_dead_tuples = tabmsg[i].t_counts.t_new_dead_tuples;
|
||||
tabentry->last_anl_tuples = 0;
|
||||
tabentry->blocks_fetched = tabmsg[i].t_counts.t_blocks_fetched;
|
||||
tabentry->blocks_hit = tabmsg[i].t_counts.t_blocks_hit;
|
||||
tabentry->numscans = tabmsg->t_counts.t_numscans;
|
||||
tabentry->tuples_returned = tabmsg->t_counts.t_tuples_returned;
|
||||
tabentry->tuples_fetched = tabmsg->t_counts.t_tuples_fetched;
|
||||
tabentry->tuples_inserted = tabmsg->t_counts.t_tuples_inserted;
|
||||
tabentry->tuples_updated = tabmsg->t_counts.t_tuples_updated;
|
||||
tabentry->tuples_deleted = tabmsg->t_counts.t_tuples_deleted;
|
||||
tabentry->tuples_hot_updated = tabmsg->t_counts.t_tuples_hot_updated;
|
||||
tabentry->n_live_tuples = tabmsg->t_counts.t_delta_live_tuples;
|
||||
tabentry->n_dead_tuples = tabmsg->t_counts.t_delta_dead_tuples;
|
||||
tabentry->changes_since_analyze = tabmsg->t_counts.t_changed_tuples;
|
||||
tabentry->blocks_fetched = tabmsg->t_counts.t_blocks_fetched;
|
||||
tabentry->blocks_hit = tabmsg->t_counts.t_blocks_hit;
|
||||
|
||||
tabentry->vacuum_timestamp = 0;
|
||||
tabentry->autovac_vacuum_timestamp = 0;
|
||||
@@ -3686,20 +3712,21 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
|
||||
/*
|
||||
* Otherwise add the values to the existing entry.
|
||||
*/
|
||||
tabentry->numscans += tabmsg[i].t_counts.t_numscans;
|
||||
tabentry->tuples_returned += tabmsg[i].t_counts.t_tuples_returned;
|
||||
tabentry->tuples_fetched += tabmsg[i].t_counts.t_tuples_fetched;
|
||||
tabentry->tuples_inserted += tabmsg[i].t_counts.t_tuples_inserted;
|
||||
tabentry->tuples_updated += tabmsg[i].t_counts.t_tuples_updated;
|
||||
tabentry->tuples_deleted += tabmsg[i].t_counts.t_tuples_deleted;
|
||||
tabentry->tuples_hot_updated += tabmsg[i].t_counts.t_tuples_hot_updated;
|
||||
tabentry->n_live_tuples += tabmsg[i].t_counts.t_new_live_tuples;
|
||||
tabentry->n_dead_tuples += tabmsg[i].t_counts.t_new_dead_tuples;
|
||||
tabentry->blocks_fetched += tabmsg[i].t_counts.t_blocks_fetched;
|
||||
tabentry->blocks_hit += tabmsg[i].t_counts.t_blocks_hit;
|
||||
tabentry->numscans += tabmsg->t_counts.t_numscans;
|
||||
tabentry->tuples_returned += tabmsg->t_counts.t_tuples_returned;
|
||||
tabentry->tuples_fetched += tabmsg->t_counts.t_tuples_fetched;
|
||||
tabentry->tuples_inserted += tabmsg->t_counts.t_tuples_inserted;
|
||||
tabentry->tuples_updated += tabmsg->t_counts.t_tuples_updated;
|
||||
tabentry->tuples_deleted += tabmsg->t_counts.t_tuples_deleted;
|
||||
tabentry->tuples_hot_updated += tabmsg->t_counts.t_tuples_hot_updated;
|
||||
tabentry->n_live_tuples += tabmsg->t_counts.t_delta_live_tuples;
|
||||
tabentry->n_dead_tuples += tabmsg->t_counts.t_delta_dead_tuples;
|
||||
tabentry->changes_since_analyze += tabmsg->t_counts.t_changed_tuples;
|
||||
tabentry->blocks_fetched += tabmsg->t_counts.t_blocks_fetched;
|
||||
tabentry->blocks_hit += tabmsg->t_counts.t_blocks_hit;
|
||||
}
|
||||
|
||||
/* Clamp n_live_tuples in case of negative new_live_tuples */
|
||||
/* Clamp n_live_tuples in case of negative delta_live_tuples */
|
||||
tabentry->n_live_tuples = Max(tabentry->n_live_tuples, 0);
|
||||
/* Likewise for n_dead_tuples */
|
||||
tabentry->n_dead_tuples = Max(tabentry->n_dead_tuples, 0);
|
||||
@@ -3707,13 +3734,13 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
|
||||
/*
|
||||
* Add per-table stats to the per-database entry, too.
|
||||
*/
|
||||
dbentry->n_tuples_returned += tabmsg[i].t_counts.t_tuples_returned;
|
||||
dbentry->n_tuples_fetched += tabmsg[i].t_counts.t_tuples_fetched;
|
||||
dbentry->n_tuples_inserted += tabmsg[i].t_counts.t_tuples_inserted;
|
||||
dbentry->n_tuples_updated += tabmsg[i].t_counts.t_tuples_updated;
|
||||
dbentry->n_tuples_deleted += tabmsg[i].t_counts.t_tuples_deleted;
|
||||
dbentry->n_blocks_fetched += tabmsg[i].t_counts.t_blocks_fetched;
|
||||
dbentry->n_blocks_hit += tabmsg[i].t_counts.t_blocks_hit;
|
||||
dbentry->n_tuples_returned += tabmsg->t_counts.t_tuples_returned;
|
||||
dbentry->n_tuples_fetched += tabmsg->t_counts.t_tuples_fetched;
|
||||
dbentry->n_tuples_inserted += tabmsg->t_counts.t_tuples_inserted;
|
||||
dbentry->n_tuples_updated += tabmsg->t_counts.t_tuples_updated;
|
||||
dbentry->n_tuples_deleted += tabmsg->t_counts.t_tuples_deleted;
|
||||
dbentry->n_blocks_fetched += tabmsg->t_counts.t_blocks_fetched;
|
||||
dbentry->n_blocks_hit += tabmsg->t_counts.t_blocks_hit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3879,36 +3906,15 @@ pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len)
|
||||
|
||||
tabentry = pgstat_get_tab_entry(dbentry, msg->m_tableoid, true);
|
||||
|
||||
if (msg->m_adopt_counts)
|
||||
tabentry->n_live_tuples = msg->m_tuples;
|
||||
/* Resetting dead_tuples to 0 is an approximation ... */
|
||||
tabentry->n_dead_tuples = 0;
|
||||
|
||||
if (msg->m_autovacuum)
|
||||
tabentry->autovac_vacuum_timestamp = msg->m_vacuumtime;
|
||||
else
|
||||
tabentry->vacuum_timestamp = msg->m_vacuumtime;
|
||||
if (msg->m_scanned_all)
|
||||
tabentry->n_live_tuples = msg->m_tuples;
|
||||
/* Resetting dead_tuples to 0 is an approximation ... */
|
||||
tabentry->n_dead_tuples = 0;
|
||||
if (msg->m_analyze)
|
||||
{
|
||||
if (msg->m_scanned_all)
|
||||
tabentry->last_anl_tuples = msg->m_tuples;
|
||||
else
|
||||
{
|
||||
/* last_anl_tuples must never exceed n_live_tuples+n_dead_tuples */
|
||||
tabentry->last_anl_tuples = Min(tabentry->last_anl_tuples,
|
||||
tabentry->n_live_tuples);
|
||||
}
|
||||
|
||||
if (msg->m_autovacuum)
|
||||
tabentry->autovac_analyze_timestamp = msg->m_vacuumtime;
|
||||
else
|
||||
tabentry->analyze_timestamp = msg->m_vacuumtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* last_anl_tuples must never exceed n_live_tuples+n_dead_tuples */
|
||||
tabentry->last_anl_tuples = Min(tabentry->last_anl_tuples,
|
||||
tabentry->n_live_tuples);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------
|
||||
@@ -3930,13 +3936,22 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
|
||||
|
||||
tabentry = pgstat_get_tab_entry(dbentry, msg->m_tableoid, true);
|
||||
|
||||
if (msg->m_adopt_counts)
|
||||
{
|
||||
tabentry->n_live_tuples = msg->m_live_tuples;
|
||||
tabentry->n_dead_tuples = msg->m_dead_tuples;
|
||||
}
|
||||
|
||||
/*
|
||||
* We reset changes_since_analyze to zero, forgetting any changes that
|
||||
* occurred while the ANALYZE was in progress.
|
||||
*/
|
||||
tabentry->changes_since_analyze = 0;
|
||||
|
||||
if (msg->m_autovacuum)
|
||||
tabentry->autovac_analyze_timestamp = msg->m_analyzetime;
|
||||
else
|
||||
tabentry->analyze_timestamp = msg->m_analyzetime;
|
||||
tabentry->n_live_tuples = msg->m_live_tuples;
|
||||
tabentry->n_dead_tuples = msg->m_dead_tuples;
|
||||
tabentry->last_anl_tuples = msg->m_live_tuples + msg->m_dead_tuples;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user