OSDN Git Service

Allow the pgstat views to show toast tables as well as regular tables
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 15 Aug 2005 16:25:19 +0000 (16:25 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 15 Aug 2005 16:25:19 +0000 (16:25 +0000)
(the stats system has always collected this info, but the views were
filtering it out).  Modify autovacuum so that over-threshold activity
in a toast table can trigger a VACUUM of the parent table, even if the
parent didn't appear to need vacuuming itself.  Per discussion a month
or so back about "short, wide tables".

src/backend/catalog/system_views.sql
src/backend/postmaster/autovacuum.c
src/backend/postmaster/pgstat.c
src/include/catalog/catversion.h
src/include/pgstat.h
src/test/regress/expected/rules.out

index 34f9d93..1f091d5 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1996-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.19 2005/08/13 19:02:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.20 2005/08/15 16:25:17 tgl Exp $
  */
 
 CREATE VIEW pg_roles AS 
@@ -190,7 +190,7 @@ CREATE VIEW pg_stat_all_tables AS
     FROM pg_class C LEFT JOIN 
          pg_index I ON C.oid = I.indrelid 
          LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) 
-    WHERE C.relkind = 'r' 
+    WHERE C.relkind IN ('r', 't')
     GROUP BY C.oid, N.nspname, C.relname;
 
 CREATE VIEW pg_stat_sys_tables AS 
@@ -223,7 +223,7 @@ CREATE VIEW pg_statio_all_tables AS
             pg_class T ON C.reltoastrelid = T.oid LEFT JOIN 
             pg_class X ON T.reltoastidxid = X.oid 
             LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) 
-    WHERE C.relkind = 'r' 
+    WHERE C.relkind IN ('r', 't')
     GROUP BY C.oid, N.nspname, C.relname, T.oid, X.oid;
 
 CREATE VIEW pg_statio_sys_tables AS 
@@ -248,7 +248,7 @@ CREATE VIEW pg_stat_all_indexes AS
             pg_index X ON C.oid = X.indrelid JOIN 
             pg_class I ON I.oid = X.indexrelid 
             LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) 
-    WHERE C.relkind = 'r';
+    WHERE C.relkind IN ('r', 't');
 
 CREATE VIEW pg_stat_sys_indexes AS 
     SELECT * FROM pg_stat_all_indexes 
@@ -272,7 +272,7 @@ CREATE VIEW pg_statio_all_indexes AS
             pg_index X ON C.oid = X.indrelid JOIN 
             pg_class I ON I.oid = X.indexrelid 
             LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) 
-    WHERE C.relkind = 'r';
+    WHERE C.relkind IN ('r', 't');
 
 CREATE VIEW pg_statio_sys_indexes AS 
     SELECT * FROM pg_statio_all_indexes 
index 3b30937..9aeecec 100644 (file)
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.3 2005/08/11 21:11:44 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.4 2005/08/15 16:25:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
 #include <signal.h>
-#include <time.h>
 #include <sys/types.h>
+#include <time.h>
 #include <unistd.h>
 
 #include "access/genam.h"
@@ -86,6 +86,7 @@ typedef struct autovac_dbase
 typedef struct autovac_table
 {
        Oid                     relid;
+       Oid                     toastrelid;
        bool            dovacuum;
        bool            doanalyze;
        int                     vacuum_cost_delay;
@@ -101,8 +102,10 @@ static void process_whole_db(void);
 static void do_autovacuum(PgStat_StatDBEntry *dbentry);
 static List *autovac_get_database_list(void);
 static void test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
-                        Form_pg_class classForm, Form_pg_autovacuum avForm,
-                        List **vacuum_tables);
+                                                                Form_pg_class classForm,
+                                                                Form_pg_autovacuum avForm,
+                                                                List **vacuum_tables,
+                                                                List **toast_table_ids);
 static void autovacuum_do_vac_analyze(List *relids, bool dovacuum,
                                                                          bool doanalyze, bool freeze);
 
@@ -387,11 +390,20 @@ AutoVacMain(int argc, char *argv[])
        if (db)
        {
                /*
+                * Report autovac startup to the stats collector.  We deliberately
+                * do this before InitPostgres, so that the last_autovac_time will
+                * get updated even if the connection attempt fails.  This is to
+                * prevent autovac from getting "stuck" repeatedly selecting an
+                * unopenable database, rather than making any progress on stuff
+                * it can connect to.
+                */
+               pgstat_report_autovac(db->oid);
+
+               /*
                 * Connect to the selected database
                 */
                InitPostgres(db->name, NULL);
                SetProcessingMode(NormalProcessing);
-               pgstat_report_autovac();
                set_ps_display(db->name);
                ereport(LOG,
                                (errmsg("autovacuum: processing database \"%s\"", db->name)));
@@ -538,6 +550,7 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
        HeapTuple               tuple;
        HeapScanDesc    relScan;
        List               *vacuum_tables = NIL;
+       List               *toast_table_ids = NIL;
        ListCell *cell;
        PgStat_StatDBEntry *shared;
 
@@ -558,9 +571,25 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
        classRel = heap_open(RelationRelationId, AccessShareLock);
        avRel = heap_open(AutovacuumRelationId, AccessShareLock);
 
+       /*
+        * Scan pg_class and determine which tables to vacuum.
+        *
+        * The stats subsystem collects stats for toast tables independently
+        * of the stats for their parent tables.  We need to check those stats
+        * since in cases with short, wide tables there might be proportionally
+        * much more activity in the toast table than in its parent.
+        *
+        * Since we can only issue VACUUM against the parent table, we need to
+        * transpose a decision to vacuum a toast table into a decision to vacuum
+        * its parent.  There's no point in considering ANALYZE on a toast table,
+        * either.  To support this, we keep a list of OIDs of toast tables that
+        * need vacuuming alongside the list of regular tables.  Regular tables
+        * will be entered into the table list even if they appear not to need
+        * vacuuming; we go back and re-mark them after finding all the
+        * vacuumable toast tables.
+        */
        relScan = heap_beginscan(classRel, SnapshotNow, 0, NULL);
 
-       /* Scan pg_class looking for tables to vacuum */
        while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
        {
                Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
@@ -571,9 +600,9 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
                ScanKeyData     entry[1];
                Oid                     relid;
 
-               /* Skip non-table entries. */
-               /* XXX possibly allow RELKIND_TOASTVALUE entries here too? */
-               if (classForm->relkind != RELKIND_RELATION)
+               /* Consider only regular and toast tables. */
+               if (classForm->relkind != RELKIND_RELATION &&
+                       classForm->relkind != RELKIND_TOASTVALUE)
                        continue;
 
                /*
@@ -607,7 +636,7 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
                                                                   HASH_FIND, NULL);
 
                test_rel_for_autovac(relid, tabentry, classForm, avForm,
-                                                        &vacuum_tables);
+                                                        &vacuum_tables, &toast_table_ids);
 
                systable_endscan(avScan);
        }
@@ -625,6 +654,22 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
 
                CHECK_FOR_INTERRUPTS();
 
+               /*
+                * Check to see if we need to force vacuuming of this table because
+                * its toast table needs it.
+                */
+               if (OidIsValid(tab->toastrelid) && !tab->dovacuum &&
+                       list_member_oid(toast_table_ids, tab->toastrelid))
+               {
+                       tab->dovacuum = true;
+                       elog(DEBUG2, "autovac: VACUUM %u because of TOAST table",
+                                tab->relid);
+               }
+
+               /* Otherwise, ignore table if it needs no work */
+               if (!tab->dovacuum && !tab->doanalyze)
+                       continue;
+
                /* Set the vacuum cost parameters for this table */
                VacuumCostDelay = tab->vacuum_cost_delay;
                VacuumCostLimit = tab->vacuum_cost_limit;
@@ -643,7 +688,7 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
  * test_rel_for_autovac
  *
  * Check whether a table needs to be vacuumed or analyzed.  Add it to the
- * output list if so.
+ * appropriate output list if so.
  *
  * A table needs to be vacuumed if the number of dead tuples exceeds a
  * threshold.  This threshold is calculated as
@@ -670,7 +715,8 @@ static void
 test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
                                         Form_pg_class classForm,
                                         Form_pg_autovacuum avForm,
-                                        List **vacuum_tables)
+                                        List **vacuum_tables,
+                                        List **toast_table_ids)
 {
        Relation                rel;
        float4                  reltuples;      /* pg_class.reltuples */
@@ -764,12 +810,10 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
         * will be reset too.
         */
 
-       elog(DEBUG2, "%s: vac: %.0f (threshold %.0f), anl: %.0f (threshold %.0f)",
+       elog(DEBUG3, "%s: vac: %.0f (threshold %.0f), anl: %.0f (threshold %.0f)",
                 RelationGetRelationName(rel),
                 vactuples, vacthresh, anltuples, anlthresh);
 
-       Assert(CurrentMemoryContext == AutovacMemCxt);
-
        /* Determine if this table needs vacuum or analyze. */
        dovacuum = (vactuples > vacthresh);
        doanalyze = (anltuples > anlthresh);
@@ -778,23 +822,40 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
        if (relid == StatisticRelationId)
                doanalyze = false;
 
-       if (dovacuum || doanalyze)
+       Assert(CurrentMemoryContext == AutovacMemCxt);
+
+       if (classForm->relkind == RELKIND_RELATION)
        {
-               autovac_table *tab;
+               if (dovacuum || doanalyze)
+                       elog(DEBUG2, "autovac: will%s%s %s",
+                                (dovacuum ? " VACUUM" : ""),
+                                (doanalyze ? " ANALYZE" : ""),
+                                RelationGetRelationName(rel));
 
-               elog(DEBUG2, "will%s%s %s",
-                        (dovacuum ? " VACUUM" : ""),
-                        (doanalyze ? " ANALYZE" : ""),
-                        RelationGetRelationName(rel));
+               /*
+                * we must record tables that have a toast table, even if we currently
+                * don't think they need vacuuming.
+                */
+               if (dovacuum || doanalyze || OidIsValid(classForm->reltoastrelid))
+               {
+                       autovac_table *tab;
 
-               tab = (autovac_table *) palloc(sizeof(autovac_table));
-               tab->relid = relid;
-               tab->dovacuum = dovacuum;
-               tab->doanalyze = doanalyze;
-               tab->vacuum_cost_limit = vac_cost_limit;
-               tab->vacuum_cost_delay = vac_cost_delay;
+                       tab = (autovac_table *) palloc(sizeof(autovac_table));
+                       tab->relid = relid;
+                       tab->toastrelid = classForm->reltoastrelid;
+                       tab->dovacuum = dovacuum;
+                       tab->doanalyze = doanalyze;
+                       tab->vacuum_cost_limit = vac_cost_limit;
+                       tab->vacuum_cost_delay = vac_cost_delay;
 
-               *vacuum_tables = lappend(*vacuum_tables, tab);
+                       *vacuum_tables = lappend(*vacuum_tables, tab);
+               }
+       }
+       else
+       {
+               Assert(classForm->relkind == RELKIND_TOASTVALUE);
+               if (dovacuum)
+                       *toast_table_ids = lappend_oid(*toast_table_ids, relid);
        }
 
        RelationClose(rel);
index bbb1027..0d1128d 100644 (file)
@@ -13,7 +13,7 @@
  *
  *     Copyright (c) 2001-2005, PostgreSQL Global Development Group
  *
- *     $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.105 2005/08/11 21:11:44 tgl Exp $
+ *     $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.106 2005/08/15 16:25:17 tgl Exp $
  * ----------
  */
 #include "postgres.h"
@@ -651,10 +651,12 @@ pgstat_beterm(int pid)
  * pgstat_report_autovac() -
  *
  *     Called from autovacuum.c to report startup of an autovacuum process.
+ *     We are called before InitPostgres is done, so can't rely on MyDatabaseId;
+ *     the db OID must be passed in, instead.
  * ----------
  */
 void
-pgstat_report_autovac(void)
+pgstat_report_autovac(Oid dboid)
 {
        PgStat_MsgAutovacStart msg;
 
@@ -662,7 +664,7 @@ pgstat_report_autovac(void)
                return;
 
        pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_AUTOVAC_START);
-       msg.m_databaseid = MyDatabaseId;
+       msg.m_databaseid = dboid;
        msg.m_start_time = GetCurrentTimestamp();
 
        pgstat_send(&msg, sizeof(msg));
index 069a236..abbcc25 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.298 2005/08/13 19:02:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.299 2005/08/15 16:25:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200508131
+#define CATALOG_VERSION_NO     200508151
 
 #endif
index f747928..5118fbc 100644 (file)
@@ -5,7 +5,7 @@
  *
  *     Copyright (c) 2001-2005, PostgreSQL Global Development Group
  *
- *     $PostgreSQL: pgsql/src/include/pgstat.h,v 1.35 2005/08/11 21:11:49 tgl Exp $
+ *     $PostgreSQL: pgsql/src/include/pgstat.h,v 1.36 2005/08/15 16:25:18 tgl Exp $
  * ----------
  */
 #ifndef PGSTAT_H
@@ -384,7 +384,7 @@ extern void pgstat_bestart(void);
 extern void pgstat_ping(void);
 extern void pgstat_report_activity(const char *what);
 extern void pgstat_report_tabstat(void);
-extern void pgstat_report_autovac(void);
+extern void pgstat_report_autovac(Oid dboid);
 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
                                                                 bool analyze, PgStat_Counter tuples);
 extern void pgstat_report_analyze(Oid tableoid, bool shared,
index 55b0653..756a716 100644 (file)
@@ -1286,16 +1286,16 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
  pg_settings              | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
  pg_shadow                | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, pg_authid.rolconfig AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin;
  pg_stat_activity         | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.rolname AS usename, pg_stat_get_backend_activity(s.backendid) AS current_query, pg_stat_get_backend_activity_start(s.backendid) AS query_start, pg_stat_get_backend_start(s.backendid) AS backend_start, pg_stat_get_backend_client_addr(s.backendid) AS client_addr, pg_stat_get_backend_client_port(s.backendid) AS client_port FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_authid u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.oid));
- pg_stat_all_indexes      | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'r'::"char");
- pg_stat_all_tables       | SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, pg_stat_get_numscans(c.oid) AS seq_scan, pg_stat_get_tuples_returned(c.oid) AS seq_tup_read, sum(pg_stat_get_numscans(i.indexrelid)) AS idx_scan, sum(pg_stat_get_tuples_fetched(i.indexrelid)) AS idx_tup_fetch, pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins, pg_stat_get_tuples_updated(c.oid) AS n_tup_upd, pg_stat_get_tuples_deleted(c.oid) AS n_tup_del FROM ((pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'r'::"char") GROUP BY c.oid, n.nspname, c.relname;
+ pg_stat_all_indexes      | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE ((c.relkind = 'r'::"char") OR (c.relkind = 't'::"char"));
+ pg_stat_all_tables       | SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, pg_stat_get_numscans(c.oid) AS seq_scan, pg_stat_get_tuples_returned(c.oid) AS seq_tup_read, sum(pg_stat_get_numscans(i.indexrelid)) AS idx_scan, sum(pg_stat_get_tuples_fetched(i.indexrelid)) AS idx_tup_fetch, pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins, pg_stat_get_tuples_updated(c.oid) AS n_tup_upd, pg_stat_get_tuples_deleted(c.oid) AS n_tup_del FROM ((pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE ((c.relkind = 'r'::"char") OR (c.relkind = 't'::"char")) GROUP BY c.oid, n.nspname, c.relname;
  pg_stat_database         | SELECT d.oid AS datid, d.datname, pg_stat_get_db_numbackends(d.oid) AS numbackends, pg_stat_get_db_xact_commit(d.oid) AS xact_commit, pg_stat_get_db_xact_rollback(d.oid) AS xact_rollback, (pg_stat_get_db_blocks_fetched(d.oid) - pg_stat_get_db_blocks_hit(d.oid)) AS blks_read, pg_stat_get_db_blocks_hit(d.oid) AS blks_hit FROM pg_database d;
  pg_stat_sys_indexes      | SELECT pg_stat_all_indexes.relid, pg_stat_all_indexes.indexrelid, pg_stat_all_indexes.schemaname, pg_stat_all_indexes.relname, pg_stat_all_indexes.indexrelname, pg_stat_all_indexes.idx_scan, pg_stat_all_indexes.idx_tup_read, pg_stat_all_indexes.idx_tup_fetch FROM pg_stat_all_indexes WHERE (((pg_stat_all_indexes.schemaname = 'pg_catalog'::name) OR (pg_stat_all_indexes.schemaname = 'pg_toast'::name)) OR (pg_stat_all_indexes.schemaname = 'information_schema'::name));
  pg_stat_sys_tables       | SELECT pg_stat_all_tables.relid, pg_stat_all_tables.schemaname, pg_stat_all_tables.relname, pg_stat_all_tables.seq_scan, pg_stat_all_tables.seq_tup_read, pg_stat_all_tables.idx_scan, pg_stat_all_tables.idx_tup_fetch, pg_stat_all_tables.n_tup_ins, pg_stat_all_tables.n_tup_upd, pg_stat_all_tables.n_tup_del FROM pg_stat_all_tables WHERE (((pg_stat_all_tables.schemaname = 'pg_catalog'::name) OR (pg_stat_all_tables.schemaname = 'pg_toast'::name)) OR (pg_stat_all_tables.schemaname = 'information_schema'::name));
  pg_stat_user_indexes     | SELECT pg_stat_all_indexes.relid, pg_stat_all_indexes.indexrelid, pg_stat_all_indexes.schemaname, pg_stat_all_indexes.relname, pg_stat_all_indexes.indexrelname, pg_stat_all_indexes.idx_scan, pg_stat_all_indexes.idx_tup_read, pg_stat_all_indexes.idx_tup_fetch FROM pg_stat_all_indexes WHERE (((pg_stat_all_indexes.schemaname <> 'pg_catalog'::name) AND (pg_stat_all_indexes.schemaname <> 'pg_toast'::name)) AND (pg_stat_all_indexes.schemaname <> 'information_schema'::name));
  pg_stat_user_tables      | SELECT pg_stat_all_tables.relid, pg_stat_all_tables.schemaname, pg_stat_all_tables.relname, pg_stat_all_tables.seq_scan, pg_stat_all_tables.seq_tup_read, pg_stat_all_tables.idx_scan, pg_stat_all_tables.idx_tup_fetch, pg_stat_all_tables.n_tup_ins, pg_stat_all_tables.n_tup_upd, pg_stat_all_tables.n_tup_del FROM pg_stat_all_tables WHERE (((pg_stat_all_tables.schemaname <> 'pg_catalog'::name) AND (pg_stat_all_tables.schemaname <> 'pg_toast'::name)) AND (pg_stat_all_tables.schemaname <> 'information_schema'::name));
- pg_statio_all_indexes    | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, (pg_stat_get_blocks_fetched(i.oid) - pg_stat_get_blocks_hit(i.oid)) AS idx_blks_read, pg_stat_get_blocks_hit(i.oid) AS idx_blks_hit FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'r'::"char");
+ pg_statio_all_indexes    | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, (pg_stat_get_blocks_fetched(i.oid) - pg_stat_get_blocks_hit(i.oid)) AS idx_blks_read, pg_stat_get_blocks_hit(i.oid) AS idx_blks_hit FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE ((c.relkind = 'r'::"char") OR (c.relkind = 't'::"char"));
  pg_statio_all_sequences  | SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS blks_read, pg_stat_get_blocks_hit(c.oid) AS blks_hit FROM (pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'S'::"char");
- pg_statio_all_tables     | SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS heap_blks_read, pg_stat_get_blocks_hit(c.oid) AS heap_blks_hit, sum((pg_stat_get_blocks_fetched(i.indexrelid) - pg_stat_get_blocks_hit(i.indexrelid))) AS idx_blks_read, sum(pg_stat_get_blocks_hit(i.indexrelid)) AS idx_blks_hit, (pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid)) AS toast_blks_read, pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit, (pg_stat_get_blocks_fetched(x.oid) - pg_stat_get_blocks_hit(x.oid)) AS tidx_blks_read, pg_stat_get_blocks_hit(x.oid) AS tidx_blks_hit FROM ((((pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) LEFT JOIN pg_class t ON ((c.reltoastrelid = t.oid))) LEFT JOIN pg_class x ON ((t.reltoastidxid = x.oid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'r'::"char") GROUP BY c.oid, n.nspname, c.relname, t.oid, x.oid;
+ pg_statio_all_tables     | SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS heap_blks_read, pg_stat_get_blocks_hit(c.oid) AS heap_blks_hit, sum((pg_stat_get_blocks_fetched(i.indexrelid) - pg_stat_get_blocks_hit(i.indexrelid))) AS idx_blks_read, sum(pg_stat_get_blocks_hit(i.indexrelid)) AS idx_blks_hit, (pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid)) AS toast_blks_read, pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit, (pg_stat_get_blocks_fetched(x.oid) - pg_stat_get_blocks_hit(x.oid)) AS tidx_blks_read, pg_stat_get_blocks_hit(x.oid) AS tidx_blks_hit FROM ((((pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) LEFT JOIN pg_class t ON ((c.reltoastrelid = t.oid))) LEFT JOIN pg_class x ON ((t.reltoastidxid = x.oid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE ((c.relkind = 'r'::"char") OR (c.relkind = 't'::"char")) GROUP BY c.oid, n.nspname, c.relname, t.oid, x.oid;
  pg_statio_sys_indexes    | SELECT pg_statio_all_indexes.relid, pg_statio_all_indexes.indexrelid, pg_statio_all_indexes.schemaname, pg_statio_all_indexes.relname, pg_statio_all_indexes.indexrelname, pg_statio_all_indexes.idx_blks_read, pg_statio_all_indexes.idx_blks_hit FROM pg_statio_all_indexes WHERE (((pg_statio_all_indexes.schemaname = 'pg_catalog'::name) OR (pg_statio_all_indexes.schemaname = 'pg_toast'::name)) OR (pg_statio_all_indexes.schemaname = 'information_schema'::name));
  pg_statio_sys_sequences  | SELECT pg_statio_all_sequences.relid, pg_statio_all_sequences.schemaname, pg_statio_all_sequences.relname, pg_statio_all_sequences.blks_read, pg_statio_all_sequences.blks_hit FROM pg_statio_all_sequences WHERE (((pg_statio_all_sequences.schemaname = 'pg_catalog'::name) OR (pg_statio_all_sequences.schemaname = 'pg_toast'::name)) OR (pg_statio_all_sequences.schemaname = 'information_schema'::name));
  pg_statio_sys_tables     | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.schemaname, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE (((pg_statio_all_tables.schemaname = 'pg_catalog'::name) OR (pg_statio_all_tables.schemaname = 'pg_toast'::name)) OR (pg_statio_all_tables.schemaname = 'information_schema'::name));