Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/backend/catalog/system_views.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,25 @@ CREATE VIEW pg_resqueue_status AS
queueholders int4)
ON (s.queueid = q.oid);

-- Resource queue cumulative statistics view
CREATE VIEW pg_stat_resqueues AS
SELECT
q.oid AS queueid,
q.rsqname AS queuename,
s.queries_submitted,
s.queries_admitted,
s.queries_rejected,
s.queries_completed,
s.elapsed_wait_secs AS total_wait_time_secs,
s.max_wait_secs,
s.elapsed_exec_secs AS total_exec_time_secs,
s.max_exec_secs,
s.total_cost,
s.total_memory_kb,
s.stat_reset_timestamp
FROM pg_resqueue AS q,
pg_stat_get_resqueue_stats(q.oid) AS s;

-- External table views

CREATE VIEW pg_max_external_files AS
Expand Down
6 changes: 6 additions & 0 deletions src/backend/cdb/dispatcher/cdbdisp_query.c
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,12 @@ cdbdisp_dispatchCommandInternal(DispatchCommandQueryParms *pQueryParms,
ThrowErrorData(qeError);
}

/*
* GPDB: Merge relation stats sent by QEs so QD's mod_since_analyze
* stays up to date for autovacuum triggering.
*/
pgstat_combine_from_qe(pr);

cdbdisp_returnResults(pr, cdb_pgresults);

cdbdisp_destroyDispatcherState(ds);
Expand Down
12 changes: 12 additions & 0 deletions src/backend/executor/execUtils.c
Original file line number Diff line number Diff line change
Expand Up @@ -2144,6 +2144,12 @@ void mppExecutorFinishup(QueryDesc *queryDesc)
if (ProcessDispatchResult_hook)
ProcessDispatchResult_hook(ds);

/*
* GPDB: Merge relation stats sent by QEs so QD's mod_since_analyze
* stays up to date for autovacuum triggering.
*/
pgstat_combine_from_qe(pr);

/* get num of rows processed from writer QEs. */
estate->es_processed +=
cdbdisp_sumCmdTuples(pr, primaryWriterSliceIndex);
Expand Down Expand Up @@ -2225,6 +2231,12 @@ uint64 mppExecutorWait(QueryDesc *queryDesc)
LocallyExecutingSliceIndex(queryDesc->estate),
estate->showstatctx);
}
/*
* GPDB: Merge relation stats sent by QEs so QD's mod_since_analyze
* stays up to date for autovacuum triggering.
*/
pgstat_combine_from_qe(pr);

/* get num of rows processed from writer QEs. */
es_processed +=
cdbdisp_sumCmdTuples(pr, primaryWriterSliceIndex);
Expand Down
113 changes: 66 additions & 47 deletions src/backend/postmaster/autovacuum.c
Original file line number Diff line number Diff line change
Expand Up @@ -676,16 +676,17 @@ AutoVacLauncherMain(int argc, char *argv[])
* the database chosen is connectable, the launcher will never select it and the
* worker will continue to signal for a new launcher.
*/
#if 0
/*
* Even when system is configured to use a different fetch consistency,
* for autovac we always want fresh stats.
*/
SetConfigOption("stats_fetch_consistency", "none", PGC_SUSET, PGC_S_OVERRIDE);

#if 0
/*
* In emergency mode, just start a worker (unless shutdown was requested)
* and go away.
* In GPDB, we only want an autovacuum worker to start once we know
* there is a database to vacuum. Therefore, we never want emergency mode
* to start a worker immediately.
*/
if (!AutoVacuumingActive())
{
Expand Down Expand Up @@ -1067,60 +1068,75 @@ rebuild_database_list(Oid newdb)
if (OidIsValid(newdb))
{
avl_dbase *db;
PgStat_StatDBEntry *entry;

/* only consider this database if it has a pgstat entry */
entry = pgstat_fetch_stat_dbentry(newdb);
if (entry != NULL)
{
/* we assume it isn't found because the hash was just created */
db = hash_search(dbhash, &newdb, HASH_ENTER, NULL);
/*
* In GPDB, include databases even without pgstat entries since
* newly created databases may already need auto-analyze via
* QE→QD pgstat collection.
*/

/* hash_search already filled in the key */
db->adl_score = score++;
/* next_worker is filled in later */
}
/* we assume it isn't found because the hash was just created */
db = hash_search(dbhash, &newdb, HASH_ENTER, NULL);

/* hash_search already filled in the key */
db->adl_score = score++;
/* next_worker is filled in later */
}

/* Now insert the databases from the existing list */
dlist_foreach(iter, &DatabaseList)
/*
* Get the current list of databases first, so we can cross-reference
* existing DatabaseList entries and exclude dropped databases.
* In GPDB, we include databases even without pgstat entries since
* newly created databases may need auto-analyze via QE→QD pgstat.
*/
dblist = get_database_list();

/* Build a set of current database OIDs for quick lookup */
{
avl_dbase *avdb = dlist_container(avl_dbase, adl_node, iter.cur);
avl_dbase *db;
bool found;
PgStat_StatDBEntry *entry;
HASHCTL oid_hctl;
HTAB *current_db_oids;

oid_hctl.keysize = sizeof(Oid);
oid_hctl.entrysize = sizeof(Oid);
oid_hctl.hcxt = tmpcxt;
current_db_oids = hash_create("current db oids", 20, &oid_hctl,
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
foreach(cell, dblist)
{
avw_dbase *avdb = lfirst(cell);
hash_search(current_db_oids, &(avdb->adw_datid), HASH_ENTER, NULL);
}

/*
* skip databases with no stat entries -- in particular, this gets rid
* of dropped databases
*/
entry = pgstat_fetch_stat_dbentry(avdb->adl_datid);
if (entry == NULL)
continue;
/* Now insert the databases from the existing list, skipping dropped ones */
dlist_foreach(iter, &DatabaseList)
{
avl_dbase *avdb = dlist_container(avl_dbase, adl_node, iter.cur);
avl_dbase *db;
bool found;

db = hash_search(dbhash, &(avdb->adl_datid), HASH_ENTER, &found);
/* Skip databases that no longer exist in pg_database */
if (!hash_search(current_db_oids, &(avdb->adl_datid), HASH_FIND, NULL))
continue;

if (!found)
{
/* hash_search already filled in the key */
db->adl_score = score++;
/* next_worker is filled in later */
db = hash_search(dbhash, &(avdb->adl_datid), HASH_ENTER, &found);

if (!found)
{
/* hash_search already filled in the key */
db->adl_score = score++;
/* next_worker is filled in later */
}
}

hash_destroy(current_db_oids);
}

/* finally, insert all qualifying databases not previously inserted */
dblist = get_database_list();
foreach(cell, dblist)
{
avw_dbase *avdb = lfirst(cell);
avl_dbase *db;
bool found;
PgStat_StatDBEntry *entry;

/* only consider databases with a pgstat entry */
entry = pgstat_fetch_stat_dbentry(avdb->adw_datid);
if (entry == NULL)
continue;

db = hash_search(dbhash, &(avdb->adw_datid), HASH_ENTER, &found);
/* only update the score if the database was not already on the hash */
Expand Down Expand Up @@ -1328,11 +1344,12 @@ do_start_worker(void)
tmp->adw_entry = pgstat_fetch_stat_dbentry(tmp->adw_datid);

/*
* Skip a database with no pgstat entry; it means it hasn't seen any
* activity.
* Don't skip databases without pgstat entries. In GPDB, a newly
* created database may already have tables needing auto-analyze
* (via QE→QD pgstat) before the database-level pgstat entry is
* flushed to shared memory. Treat them as candidates with the
* oldest last_autovac_time so they get visited promptly.
*/
if (!tmp->adw_entry)
continue;

/*
* Also, skip a database that appears on the database list as having
Expand Down Expand Up @@ -1367,11 +1384,13 @@ do_start_worker(void)
continue;

/*
* Remember the db with oldest autovac time. (If we are here, both
* tmp->entry and db->entry must be non-null.)
* Remember the db with oldest autovac time. A database without a
* pgstat entry is treated as having last_autovac_time = 0, giving
* it the highest priority.
*/
if (avdb == NULL ||
tmp->adw_entry->last_autovac_time < avdb->adw_entry->last_autovac_time)
(tmp->adw_entry ? tmp->adw_entry->last_autovac_time : 0) <
(avdb->adw_entry ? avdb->adw_entry->last_autovac_time : 0))
avdb = tmp;
}

Expand Down
8 changes: 8 additions & 0 deletions src/backend/tcop/postgres.c
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,14 @@ exec_mpp_query(const char *query_string,

PortalDrop(portal, false);

/*
* GPDB: Send pending relation stats to QD before closing the
* transaction. The stats are in pgStatXactStack (transaction-level
* counts); finish_xact_command() will call AtEOXact_PgStat() which
* NULLs pgStatXactStack, so we must capture the stats first.
*/
pgstat_send_qd_tabstats();

/*
* Close down transaction statement before reporting command-complete.
* This is so that any end-of-transaction errors are reported before
Expand Down
4 changes: 4 additions & 0 deletions src/backend/utils/activity/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ subdir = src/backend/utils/activity
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global

# GPDB: needed for libpq-int.h (PGExtraType, pg_result struct)
override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)

OBJS = \
backend_progress.o \
backend_status.o \
Expand All @@ -25,6 +28,7 @@ OBJS = \
pgstat_io.o \
pgstat_relation.o \
pgstat_replslot.o \
pgstat_resqueue.o \
pgstat_shmem.o \
pgstat_slru.o \
pgstat_subscription.o \
Expand Down
Loading