Remove pgstat's discrimination against MsgVacuum and MsgAnalyze messages.
authorTom Lane <[email protected]>
Fri, 4 Sep 2009 22:32:33 +0000 (22:32 +0000)
committerTom Lane <[email protected]>
Fri, 4 Sep 2009 22:32:33 +0000 (22:32 +0000)
Formerly, these message types would be discarded unless there was already
a stats hash table entry for the target table.  However, the intent of
saving hash table space for unused tables was subverted by the fact that
the physical I/O done by the vacuum or analyze would result in an immediately
following tabstat message, which would create the hash table entry anyway.
All that we had left was surprising loss of statistical data, as in a recent
complaint from Jaime Casanova.

It seems unlikely that a real database would have many tables that go totally
untouched over the long haul, so the consensus is that this "optimization"
serves little purpose anyhow.  Remove it, and just create the hash table
entry on demand in all cases.

src/backend/postmaster/pgstat.c

index dbb9f95cc33b47cef3b21f881e046066d0a57e8a..d409b50d934fd3a1fad5cadba7f32b4b8bdbc458 100644 (file)
@@ -246,6 +246,8 @@ static void pgstat_beshutdown_hook(int code, Datum arg);
 static void pgstat_sighup_handler(SIGNAL_ARGS);
 
 static PgStat_StatDBEntry *pgstat_get_db_entry(Oid databaseid, bool create);
+static PgStat_StatTabEntry *pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry,
+                                                                                                Oid tableoid, bool create);
 static void pgstat_write_statsfile(bool permanent);
 static HTAB *pgstat_read_statsfile(Oid onlydb, bool permanent);
 static void backend_read_statsfile(void);
@@ -2940,6 +2942,52 @@ pgstat_get_db_entry(Oid databaseid, bool create)
 }
 
 
+/*
+ * Lookup the hash table entry for the specified table. If no hash
+ * table entry exists, initialize it, if the create parameter is true.
+ * Else, return NULL.
+ */
+static PgStat_StatTabEntry *
+pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry, Oid tableoid, bool create)
+{
+       PgStat_StatTabEntry *result;
+       bool            found;
+       HASHACTION      action = (create ? HASH_ENTER : HASH_FIND);
+
+       /* Lookup or create the hash table entry for this table */
+       result = (PgStat_StatTabEntry *) hash_search(dbentry->tables,
+                                                                                                &tableoid,
+                                                                                                action, &found);
+
+       if (!create && !found)
+               return NULL;
+
+       /* If not found, initialize the new one. */
+       if (!found)
+       {
+               result->numscans = 0;
+               result->tuples_returned = 0;
+               result->tuples_fetched = 0;
+               result->tuples_inserted = 0;
+               result->tuples_updated = 0;
+               result->tuples_deleted = 0;
+               result->tuples_hot_updated = 0;
+               result->n_live_tuples = 0;
+               result->n_dead_tuples = 0;
+               result->last_anl_tuples = 0;
+               result->blocks_fetched = 0;
+               result->blocks_hit = 0;
+
+               result->vacuum_timestamp = 0;
+               result->autovac_vacuum_timestamp = 0;
+               result->analyze_timestamp = 0;
+               result->autovac_analyze_timestamp = 0;
+       }
+
+       return result;
+}
+
+
 /* ----------
  * pgstat_write_statsfile() -
  *
@@ -3553,10 +3601,10 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
                        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->last_anl_tuples = 0;
                        tabentry->vacuum_timestamp = 0;
                        tabentry->autovac_vacuum_timestamp = 0;
                        tabentry->analyze_timestamp = 0;
@@ -3734,19 +3782,10 @@ pgstat_recv_autovac(PgStat_MsgAutovacStart *msg, int len)
        PgStat_StatDBEntry *dbentry;
 
        /*
-        * Lookup the database in the hashtable.  Don't create the entry if it
-        * doesn't exist, because autovacuum may be processing a template
-        * database.  If this isn't the case, the database is most likely to have
-        * an entry already.  (If it doesn't, not much harm is done anyway --
-        * it'll get created as soon as somebody actually uses the database.)
+        * Store the last autovacuum time in the database's hashtable entry.
         */
-       dbentry = pgstat_get_db_entry(msg->m_databaseid, false);
-       if (dbentry == NULL)
-               return;
+       dbentry = pgstat_get_db_entry(msg->m_databaseid, true);
 
-       /*
-        * Store the last autovacuum time in the database entry.
-        */
        dbentry->last_autovac_time = msg->m_start_time;
 }
 
@@ -3763,18 +3802,11 @@ pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len)
        PgStat_StatTabEntry *tabentry;
 
        /*
-        * Don't create either the database or table entry if it doesn't already
-        * exist.  This avoids bloating the stats with entries for stuff that is
-        * only touched by vacuum and not by live operations.
+        * Store the data in the table's hashtable entry.
         */
-       dbentry = pgstat_get_db_entry(msg->m_databaseid, false);
-       if (dbentry == NULL)
-               return;
+       dbentry = pgstat_get_db_entry(msg->m_databaseid, true);
 
-       tabentry = hash_search(dbentry->tables, &(msg->m_tableoid),
-                                                  HASH_FIND, NULL);
-       if (tabentry == NULL)
-               return;
+       tabentry = pgstat_get_tab_entry(dbentry, msg->m_tableoid, true);
 
        if (msg->m_autovacuum)
                tabentry->autovac_vacuum_timestamp = msg->m_vacuumtime;
@@ -3821,18 +3853,11 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
        PgStat_StatTabEntry *tabentry;
 
        /*
-        * Don't create either the database or table entry if it doesn't already
-        * exist.  This avoids bloating the stats with entries for stuff that is
-        * only touched by analyze and not by live operations.
+        * Store the data in the table's hashtable entry.
         */
-       dbentry = pgstat_get_db_entry(msg->m_databaseid, false);
-       if (dbentry == NULL)
-               return;
+       dbentry = pgstat_get_db_entry(msg->m_databaseid, true);
 
-       tabentry = hash_search(dbentry->tables, &(msg->m_tableoid),
-                                                  HASH_FIND, NULL);
-       if (tabentry == NULL)
-               return;
+       tabentry = pgstat_get_tab_entry(dbentry, msg->m_tableoid, true);
 
        if (msg->m_autovacuum)
                tabentry->autovac_analyze_timestamp = msg->m_analyzetime;