<!--
-$PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.28 2005/05/09 11:31:32 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.29 2005/10/06 02:29:06 tgl Exp $
-->
<chapter id="monitoring">
Each individual server process transmits new block and row access counts to
the collector just before going idle; so a query or transaction still in
progress does not affect the displayed totals. Also, the collector itself
- emits a new report at most once per <varname>pgstat_stat_interval</varname>
- milliseconds (500 by default). So the displayed information lags behind
- actual activity. Current-query information is reported to the collector
- immediately, but is still subject to the
- <varname>pgstat_stat_interval</varname> delay before it becomes visible.
+ emits a new report at most once per <varname>PGSTAT_STAT_INTERVAL</varname>
+ milliseconds (500 unless altered while building the server). So the
+ displayed information lags behind actual activity. Current-query
+ information is reported to the collector immediately, but is still subject
+ to the <varname>PGSTAT_STAT_INTERVAL</varname> delay before it becomes
+ visible.
</para>
<para>
<tbody>
<row>
<entry><structname>pg_stat_activity</></entry>
- <entry>One row per server process, showing process
- <acronym>ID</>, database, user, current query, the time at which
- the current query began execution, the time at which the backend
- was started and the client address and port number. The columns
+ <entry>One row per server process, showing database OID, database name,
+ process <acronym>ID</>, user OID, user name, current query, time at
+ which the current query began execution, time at which the process
+ was started, and client's address and port number. The columns
that report data on the current query are only available if the
parameter <varname>stats_command_string</varname> has been
turned on. Furthermore, these columns read as null unless the
<row>
<entry><structname>pg_stat_database</></entry>
- <entry>One row per database, showing the number of active backend server processes,
- total transactions committed and total rolled back in that database,
- total disk blocks read, and total number of buffer hits (i.e., block
+ <entry>One row per database, showing database OID, database name,
+ number of active server processes connected to that database,
+ number of transactions committed and rolled back in that database,
+ total disk blocks read, and total buffer hits (i.e., block
read requests avoided by finding the block already in buffer cache).
</entry>
</row>
<row>
<entry><structname>pg_stat_all_tables</></entry>
- <entry>For each table in the current database, total numbers of
- sequential and index scans, total numbers of rows returned by
- each type of scan, and totals of row insertions, updates,
- and deletions.</entry>
+ <entry>For each table in the current database (including TOAST tables),
+ the table OID, schema and table name, number of sequential
+ scans initiated, number of live rows fetched by sequential
+ scans, number of index scans initiated (over all indexes
+ belonging to the table), number of live rows fetched by index
+ scans,
+ and numbers of row insertions, updates, and deletions.</entry>
</row>
<row>
<entry><structname>pg_stat_sys_tables</></entry>
- <entry>Same as <structname>pg_stat_all_tables</>, except that only system tables
- are shown.</entry>
+ <entry>Same as <structname>pg_stat_all_tables</>, except that only
+ system tables are shown.</entry>
</row>
<row>
<entry><structname>pg_stat_user_tables</></entry>
- <entry>Same as <structname>pg_stat_all_tables</>, except that only user tables
- are shown.</entry>
+ <entry>Same as <structname>pg_stat_all_tables</>, except that only user
+ tables are shown.</entry>
</row>
<row>
<entry><structname>pg_stat_all_indexes</></entry>
- <entry>For each index in the current database, the total number
- of index scans that have used that index, the number of index rows
- read, and the number of successfully fetched heap rows. (This may
- be less when there are index entries pointing to expired heap rows.)
+ <entry>For each index in the current database,
+ the table and index OID, schema, table and index name,
+ number of index scans initiated on that index, number of
+ index entries returned by index scans, and number of live table rows
+ fetched by simple index scans using that index.
</entry>
</row>
<row>
<entry><structname>pg_stat_sys_indexes</></entry>
- <entry>Same as <structname>pg_stat_all_indexes</>, except that only indexes on
- system tables are shown.</entry>
+ <entry>Same as <structname>pg_stat_all_indexes</>, except that only
+ indexes on system tables are shown.</entry>
</row>
<row>
<entry><structname>pg_stat_user_indexes</></entry>
- <entry>Same as <structname>pg_stat_all_indexes</>, except that only indexes on
- user tables are shown.</entry>
+ <entry>Same as <structname>pg_stat_all_indexes</>, except that only
+ indexes on user tables are shown.</entry>
</row>
<row>
<entry><structname>pg_statio_all_tables</></entry>
- <entry>For each table in the current database, the total number of disk
- blocks read from that table, the number of buffer hits, the numbers of
- disk blocks read and buffer hits in all the indexes of that table,
- the numbers of disk blocks read and buffer hits from the table's
- auxiliary TOAST table (if any), and the numbers of disk blocks read
+ <entry>For each table in the current database (including TOAST tables),
+ the table OID, schema and table name, number of disk
+ blocks read from that table, number of buffer hits, numbers of
+ disk blocks read and buffer hits in all indexes of that table,
+ numbers of disk blocks read and buffer hits from that table's
+ auxiliary TOAST table (if any), and numbers of disk blocks read
and buffer hits for the TOAST table's index.
</entry>
</row>
<row>
<entry><structname>pg_statio_sys_tables</></entry>
- <entry>Same as <structname>pg_statio_all_tables</>, except that only system tables
- are shown.</entry>
+ <entry>Same as <structname>pg_statio_all_tables</>, except that only
+ system tables are shown.</entry>
</row>
<row>
<entry><structname>pg_statio_user_tables</></entry>
- <entry>Same as <structname>pg_statio_all_tables</>, except that only user tables
- are shown.</entry>
+ <entry>Same as <structname>pg_statio_all_tables</>, except that only
+ user tables are shown.</entry>
</row>
<row>
<entry><structname>pg_statio_all_indexes</></entry>
- <entry>For each index in the current database, the numbers of
- disk blocks read and buffer hits in that index.
+ <entry>For each index in the current database,
+ the table and index OID, schema, table and index name,
+ numbers of disk blocks read and buffer hits in that index.
</entry>
</row>
<row>
<entry><structname>pg_statio_sys_indexes</></entry>
- <entry>Same as <structname>pg_statio_all_indexes</>, except that only indexes on
- system tables are shown.</entry>
+ <entry>Same as <structname>pg_statio_all_indexes</>, except that only
+ indexes on system tables are shown.</entry>
</row>
<row>
<entry><structname>pg_statio_user_indexes</></entry>
- <entry>Same as <structname>pg_statio_all_indexes</>, except that only indexes on
- user tables are shown.</entry>
+ <entry>Same as <structname>pg_statio_all_indexes</>, except that only
+ indexes on user tables are shown.</entry>
</row>
<row>
<entry><structname>pg_statio_all_sequences</></entry>
- <entry>For each sequence object in the current database, the numbers
- of disk blocks read and buffer hits in that sequence.
+ <entry>For each sequence object in the current database,
+ the sequence OID, schema and sequence name,
+ numbers of disk blocks read and buffer hits in that sequence.
</entry>
</row>
<row>
<entry><structname>pg_statio_sys_sequences</></entry>
- <entry>Same as <structname>pg_statio_all_sequences</>, except that only system
- sequences are shown. (Presently, no system sequences are defined,
+ <entry>Same as <structname>pg_statio_all_sequences</>, except that only
+ system sequences are shown. (Presently, no system sequences are defined,
so this view is always empty.)</entry>
</row>
<row>
<entry><structname>pg_statio_user_sequences</></entry>
- <entry>Same as <structname>pg_statio_all_sequences</>, except that only user
- sequences are shown.</entry>
+ <entry>Same as <structname>pg_statio_all_sequences</>, except that only
+ user sequences are shown.</entry>
</row>
</tbody>
</tgroup>
indexes are being used and how effective they are.
</para>
+ <para>
+ Beginning in <productname>PostgreSQL</productname> 8.1, indexes can be
+ used either directly or via <quote>bitmap scans</>. In a bitmap scan
+ the output of several indexes can be combined via AND or OR rules;
+ so it is difficult to associate individual heap row fetches
+ with specific indexes when a bitmap scan is used. Therefore, a bitmap
+ scan increments the
+ <structname>pg_stat_all_indexes</>.<structfield>idx_tup_read</>
+ count(s) for the index(es) it uses, and it increments the
+ <structname>pg_stat_all_tables</>.<structfield>idx_tup_fetch</>
+ count for the table, but it does not affect
+ <structname>pg_stat_all_indexes</>.<structfield>idx_tup_fetch</>.
+ </para>
+
+ <note>
+ <para>
+ Before <productname>PostgreSQL</productname> 8.1, the
+ <structfield>idx_tup_read</> and <structfield>idx_tup_fetch</> counts
+ were essentially always equal. Now they can be different even without
+ considering bitmap scans, because <structfield>idx_tup_read</> counts
+ index entries retrieved from the index while <structfield>idx_tup_fetch</>
+ counts live rows fetched from the table; the latter will be less if any
+ dead or not-yet-committed rows are fetched using the index.
+ </para>
+ </note>
+
<para>
The <structname>pg_statio_</> views are primarily useful to
determine the effectiveness of the buffer cache. When the number
database to report on. The per-table and per-index functions take
a table or index OID. (Note that only tables and indexes in the
current database can be seen with these functions.) The
- per-backend process access functions take a backend process ID
+ per-server-process access functions take a server process
number, which ranges from one to the number of currently active
- backend processes.
+ server processes.
</para>
<table id="monitoring-stats-funcs-table">
<entry><literal><function>pg_stat_get_db_numbackends</function>(<type>oid</type>)</literal></entry>
<entry><type>integer</type></entry>
<entry>
- Number of active backend processes for database
+ Number of active server processes for database
</entry>
</row>
<entry><type>bigint</type></entry>
<entry>
Number of rows read by sequential scans when argument is a table,
- or number of index rows read when argument is an index
+ or number of index entries returned when argument is an index
</entry>
</row>
<entry><literal><function>pg_stat_get_tuples_fetched</function>(<type>oid</type>)</literal></entry>
<entry><type>bigint</type></entry>
<entry>
- Number of valid (unexpired) table rows fetched by sequential scans
- when argument is a table, or fetched by index scans using this index
+ Number of table rows fetched by bitmap scans when argument is a table,
+ or table rows fetched by simple index scans using the index
when argument is an index
</entry>
</row>
<row>
<entry><literal><function>pg_stat_get_backend_idset</function>()</literal></entry>
- <entry><type>set of integer</type></entry>
+ <entry><type>setof integer</type></entry>
<entry>
- Set of currently active backend process IDs (from 1 to the
- number of active backend processes). See usage example in the text
+ Set of currently active server process numbers (from 1 to the
+ number of active server processes). See usage example in the text
</entry>
</row>
<entry><literal><function>pg_backend_pid</function>()</literal></entry>
<entry><type>integer</type></entry>
<entry>
- Process ID of the backend process attached to the current session
+ Process ID of the server process attached to the current session
</entry>
</row>
<entry><literal><function>pg_stat_get_backend_pid</function>(<type>integer</type>)</literal></entry>
<entry><type>integer</type></entry>
<entry>
- Process ID of the given backend process
+ Process ID of the given server process
</entry>
</row>
<entry><literal><function>pg_stat_get_backend_dbid</function>(<type>integer</type>)</literal></entry>
<entry><type>oid</type></entry>
<entry>
- Database ID of the given backend process
+ Database ID of the given server process
</entry>
</row>
<entry><literal><function>pg_stat_get_backend_userid</function>(<type>integer</type>)</literal></entry>
<entry><type>oid</type></entry>
<entry>
- User ID of the given backend process
+ User ID of the given server process
</entry>
</row>
<entry><literal><function>pg_stat_get_backend_activity</function>(<type>integer</type>)</literal></entry>
<entry><type>text</type></entry>
<entry>
- Active command of the given backend process (null if the
+ Active command of the given server process (null if the
current user is not a superuser nor the same user as that of
the session being queried, or
<varname>stats_command_string</varname> is not on)
<entry><literal><function>pg_stat_get_backend_activity_start</function>(<type>integer</type>)</literal></entry>
<entry><type>timestamp with time zone</type></entry>
<entry>
- The time at which the given backend process' currently
+ The time at which the given server process' currently
executing query was started (null if the
current user is not a superuser nor the same user as that of
the session being queried, or
<entry><literal><function>pg_stat_get_backend_start</function>(<type>integer</type>)</literal></entry>
<entry><type>timestamp with time zone</type></entry>
<entry>
- The time at which the given backend process was started, or
+ The time at which the given server process was started, or
null if the current user is not a superuser nor the same user
as that of the session being queried
</entry>
<entry><type>inet</type></entry>
<entry>
The IP address of the client connected to the given
- backend. Null if the connection is over a Unix domain
+ server process. Null if the connection is over a Unix domain
socket. Also null if the current user is not a superuser nor
the same user as that of the session being queried
</entry>
<entry><type>integer</type></entry>
<entry>
The IP port number of the client connected to the given
- backend. -1 if the connection is over a Unix domain
+ server process. -1 if the connection is over a Unix domain
socket. Null if the current user is not a superuser nor the
same user as that of the session being queried
</entry>
<note>
<para>
- <function>pg_stat_get_db_blocks_fetched</function> minus
- <function>pg_stat_get_db_blocks_hit</function> gives the number of kernel
+ <function>blocks_fetched</function> minus
+ <function>blocks_hit</function> gives the number of kernel
<function>read()</> calls issued for the table, index, or
database; but the actual number of physical reads is usually
lower due to kernel-level buffering.
<para>
The function <function>pg_stat_get_backend_idset</function> provides
- a convenient way to generate one row for each active backend process. For
- example, to show the <acronym>PID</>s and current queries of all backend processes:
+ a convenient way to generate one row for each active server process. For
+ example, to show the <acronym>PID</>s and current queries of all server processes:
<programlisting>
SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.51 2005/09/22 20:44:36 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.52 2005/10/06 02:29:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/itup.h"
#include "access/gist_private.h"
#include "executor/execdebug.h"
+#include "pgstat.h"
#include "utils/memutils.h"
+
static OffsetNumber gistfindnext(IndexScanDesc scan, OffsetNumber n,
ScanDirection dir);
static int gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, bool ignore_killed_tuples);
stk->next = NULL;
stk->block = GIST_ROOT_BLKNO;
+
+ pgstat_count_index_scan(&scan->xs_pgstat_info);
}
else if (so->curbuf == InvalidBuffer)
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.38 2004/12/31 21:59:13 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.39 2005/10/06 02:29:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/hash.h"
+#include "pgstat.h"
#include "storage/lmgr.h"
ItemPointer current;
OffsetNumber offnum;
+ pgstat_count_index_scan(&scan->xs_pgstat_info);
+
current = &(scan->currentItemData);
ItemPointerSetInvalid(current);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.198 2005/08/20 00:39:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.199 2005/10/06 02:29:10 tgl Exp $
*
*
* INTERFACE ROUTINES
#include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "storage/procarray.h"
#include "utils/inval.h"
#include "utils/relcache.h"
-#include "pgstat.h"
static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf,
*/
if (key != NULL)
memcpy(scan->rs_key, key, scan->rs_nkeys * sizeof(ScanKeyData));
+
+ pgstat_count_heap_scan(&scan->rs_pgstat_info);
}
/* ----------------
* reinitialize scan descriptor
*/
initscan(scan, key);
-
- pgstat_reset_heap_scan(&scan->rs_pgstat_info);
}
/* ----------------
return NULL;
}
- pgstat_count_heap_scan(&scan->rs_pgstat_info);
-
/*
* if we get here it means we have a new current scan tuple, so point
* to the proper return buffer and return the tuple.
*/
*userbuf = buffer;
- /*
- * Count the successful fetch in *pgstat_info if given, otherwise
- * in the relation's default statistics area.
- */
+ /* Count the successful fetch in *pgstat_info, if given. */
if (pgstat_info != NULL)
pgstat_count_heap_fetch(pgstat_info);
- else
- pgstat_count_heap_fetch(&relation->pgstat_info);
return true;
}
RelationPutHeapTuple(relation, buffer, tup);
- pgstat_count_heap_insert(&relation->pgstat_info);
-
/* XLOG stuff */
if (relation->rd_istemp)
{
*/
CacheInvalidateHeapTuple(relation, tup);
+ pgstat_count_heap_insert(&relation->pgstat_info);
+
return HeapTupleGetOid(tup);
}
if (HeapTupleHasExternal(&tp))
heap_tuple_toast_attrs(relation, NULL, &tp);
- pgstat_count_heap_delete(&relation->pgstat_info);
-
/*
* Mark tuple for invalidation from system caches at next command
* boundary. We have to do this before WriteBuffer because we need to
if (have_tuple_lock)
UnlockTuple(relation, &(tp.t_self), ExclusiveLock);
+ pgstat_count_heap_delete(&relation->pgstat_info);
+
return HeapTupleMayBeUpdated;
}
newbuf = buffer;
}
- pgstat_count_heap_update(&relation->pgstat_info);
-
/*
* At this point newbuf and buffer are both pinned and locked, and
* newbuf has enough space for the new tuple. If they are the same
if (have_tuple_lock)
UnlockTuple(relation, &(oldtup.t_self), ExclusiveLock);
+ pgstat_count_heap_update(&relation->pgstat_info);
+
return HeapTupleMayBeUpdated;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.84 2005/06/27 12:45:22 teodor Exp $
+ * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.85 2005/10/06 02:29:11 tgl Exp $
*
* INTERFACE ROUTINES
* index_open - open an index relation by relation OID
#include "access/genam.h"
#include "access/heapam.h"
+#include "pgstat.h"
#include "utils/relcache.h"
-#include "pgstat.h"
/* ----------------------------------------------------------------
* macros used in index_ routines
FunctionCall2(procedure,
PointerGetDatum(scan),
PointerGetDatum(key));
-
- pgstat_reset_index_scan(&scan->xs_pgstat_info);
}
/* ----------------
{
bool found;
- pgstat_count_index_scan(&scan->xs_pgstat_info);
-
/*
* The AM's gettuple proc finds the next tuple matching the scan
* keys.
return NULL; /* failure exit */
}
+ pgstat_count_index_tuples(&scan->xs_pgstat_info, 1);
+
/*
* Fetch the heap tuple and see if it matches the snapshot.
*/
* initialized to 0, which is the correct state ("on row").
*/
- pgstat_count_index_getnext(&scan->xs_pgstat_info);
-
return heapTuple;
}
PointerGetDatum(scan),
Int32GetDatum(direction)));
+ if (found)
+ pgstat_count_index_tuples(&scan->xs_pgstat_info, 1);
+
return found;
}
Int32GetDatum(max_tids),
PointerGetDatum(returned_tids)));
+ pgstat_count_index_tuples(&scan->xs_pgstat_info, *returned_tids);
+
return found;
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.93 2005/06/19 22:41:00 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.94 2005/10/06 02:29:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/genam.h"
#include "access/nbtree.h"
+#include "pgstat.h"
#include "utils/lsyscache.h"
int i;
StrategyNumber strat_total;
+ pgstat_count_index_scan(&scan->xs_pgstat_info);
+
/*
* Examine the scan keys and eliminate any redundant keys; also
* discover how many keys must be matched to continue the scan.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/rtree/rtget.c,v 1.35 2005/03/27 23:53:02 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/rtree/rtget.c,v 1.36 2005/10/06 02:29:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/iqual.h"
#include "access/relscan.h"
#include "access/rtree.h"
+#include "pgstat.h"
+
static OffsetNumber findnext(IndexScanDesc s, OffsetNumber n,
ScanDirection dir);
/* first call: start at the root */
Assert(BufferIsValid(so->curbuf) == false);
so->curbuf = ReadBuffer(s->indexRelation, P_ROOT);
+ pgstat_count_index_scan(&s->xs_pgstat_info);
}
p = BufferGetPage(so->curbuf);
*
* Copyright (c) 1996-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.21 2005/08/15 23:00:13 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.22 2005/10/06 02:29:15 tgl Exp $
*/
CREATE VIEW pg_roles AS
C.relname AS 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,
+ sum(pg_stat_get_numscans(I.indexrelid))::bigint AS idx_scan,
+ sum(pg_stat_get_tuples_fetched(I.indexrelid))::bigint +
+ pg_stat_get_tuples_fetched(C.oid) 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
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_hit(I.indexrelid))::bigint AS idx_blks_read,
+ sum(pg_stat_get_blocks_hit(I.indexrelid))::bigint 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,
'bool'],
proargmodes = ARRAY['i'::"char", 'o', 'o', 'o', 'o', 'o', 'o'],
proargnames = ARRAY['filename'::text, 'size', 'access', 'modification',
- 'change', 'creation', 'isdir']
+ 'change', 'creation', 'isdir']
WHERE oid = 'pg_stat_file(text)'::regprocedure;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.2 2005/05/06 17:24:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.3 2005/10/06 02:29:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "executor/execdebug.h"
#include "executor/nodeBitmapHeapscan.h"
#include "parser/parsetree.h"
+#include "pgstat.h"
#include "utils/memutils.h"
/* rescan to release any page pin */
heap_rescan(node->ss.ss_currentScanDesc, NULL);
+ /* undo bogus "seq scan" count (see notes in ExecInitBitmapHeapScan) */
+ pgstat_discount_heap_scan(&node->ss.ss_currentScanDesc->rs_pgstat_info);
+
if (node->tbm)
tbm_free(node->tbm);
node->tbm = NULL;
0,
NULL);
+ /*
+ * One problem is that heap_beginscan counts a "sequential scan" start,
+ * when we actually aren't doing any such thing. Reverse out the added
+ * scan count. (Eventually we may want to count bitmap scans separately.)
+ */
+ pgstat_discount_heap_scan(&scanstate->ss.ss_currentScanDesc->rs_pgstat_info);
+
/*
* get the scan type from the relation descriptor.
*/
*
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.108 2005/09/24 17:53:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.109 2005/10/06 02:29:17 tgl Exp $
* ----------
*/
#include "postgres.h"
* Initialize data not to count at all.
*/
stats->tabentry = NULL;
- stats->no_stats = FALSE;
- stats->heap_scan_counted = FALSE;
- stats->index_scan_counted = FALSE;
if (pgStatSock < 0 ||
!(pgstat_collect_tuplelevel ||
pgstat_collect_blocklevel))
- {
- stats->no_stats = TRUE;
return;
- }
tsarr = rel->rd_rel->relisshared ? &SharedTabStat : &RegularTabStat;
* 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.303 2005/10/02 23:50:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.304 2005/10/06 02:29:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200510011
+#define CATALOG_VERSION_NO 200510051
#endif
*
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.36 2005/08/15 16:25:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.37 2005/10/06 02:29:19 tgl Exp $
* ----------
*/
#ifndef PGSTAT_H
/* ----------
* PgStat_TableEntry Per-table info in a MsgTabstat
+ *
+ * Note: for a table, tuples_returned is the number of tuples successfully
+ * fetched by heap_getnext, while tuples_fetched is the number of tuples
+ * successfully fetched by heap_fetch under the control of bitmap indexscans.
+ * For an index, tuples_returned is the number of index entries returned by
+ * the index AM, while tuples_fetched is the number of tuples successfully
+ * fetched by heap_fetch under the control of simple indexscans for this index.
* ----------
*/
typedef struct PgStat_TableEntry
PgStat_Counter t_tuples_returned;
PgStat_Counter t_tuples_fetched;
+
PgStat_Counter t_tuples_inserted;
PgStat_Counter t_tuples_updated;
PgStat_Counter t_tuples_deleted;
* and buffer access statistics.
* ----------
*/
-#define PGSTAT_NUM_TABENTRIES ((PGSTAT_MSG_PAYLOAD - 3 * sizeof(int)) \
- / sizeof(PgStat_TableEntry))
+#define PGSTAT_NUM_TABENTRIES \
+ ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - 3 * sizeof(int)) \
+ / sizeof(PgStat_TableEntry))
typedef struct PgStat_MsgTabstat
{
* about dead tables.
* ----------
*/
-#define PGSTAT_NUM_TABPURGE ((PGSTAT_MSG_PAYLOAD - sizeof(int)) \
- / sizeof(Oid))
+#define PGSTAT_NUM_TABPURGE \
+ ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int)) \
+ / sizeof(Oid))
typedef struct PgStat_MsgTabpurge
{
/* ----------
* PgStat_MsgDropdb Sent by the backend to tell the collector
- * about dropped database
+ * about a dropped database
* ----------
*/
typedef struct PgStat_MsgDropdb
#define PGSTAT_FILE_FORMAT_ID 0x01A5BC93
/* ----------
- * PgStat_StatDBEntry The collectors data per database
+ * PgStat_StatDBEntry The collector's data per database
* ----------
*/
typedef struct PgStat_StatDBEntry
/* ----------
- * PgStat_StatBeEntry The collectors data per backend
+ * PgStat_StatBeEntry The collector's data per backend
* ----------
*/
typedef struct PgStat_StatBeEntry
/* ----------
- * PgStat_StatTabEntry The collectors data table data
+ * PgStat_StatTabEntry The collector's data per table (or index)
* ----------
*/
typedef struct PgStat_StatTabEntry
PgStat_Counter tuples_returned;
PgStat_Counter tuples_fetched;
+
PgStat_Counter tuples_inserted;
PgStat_Counter tuples_updated;
PgStat_Counter tuples_deleted;
extern void pgstat_initstats(PgStat_Info *stats, Relation rel);
-#define pgstat_reset_heap_scan(s) \
+#define pgstat_count_heap_scan(s) \
do { \
if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
- (s)->heap_scan_counted = FALSE; \
+ ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++; \
} while (0)
-#define pgstat_count_heap_scan(s) \
+/* kluge for bitmap scans: */
+#define pgstat_discount_heap_scan(s) \
do { \
- if (pgstat_collect_tuplelevel && (s)->tabentry != NULL && \
- !(s)->heap_scan_counted) { \
- ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++; \
- (s)->heap_scan_counted = TRUE; \
- } \
+ if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
+ ((PgStat_TableEntry *)((s)->tabentry))->t_numscans--; \
} while (0)
#define pgstat_count_heap_getnext(s) \
do { \
if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
((PgStat_TableEntry *)((s)->tabentry))->t_tuples_deleted++; \
} while (0)
-#define pgstat_reset_index_scan(s) \
- do { \
- if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
- (s)->index_scan_counted = FALSE; \
- } while (0)
#define pgstat_count_index_scan(s) \
do { \
- if (pgstat_collect_tuplelevel && (s)->tabentry != NULL && \
- !(s)->index_scan_counted) { \
+ if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
((PgStat_TableEntry *)((s)->tabentry))->t_numscans++; \
- (s)->index_scan_counted = TRUE; \
- } \
} while (0)
-#define pgstat_count_index_getnext(s) \
+#define pgstat_count_index_tuples(s, n) \
do { \
if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
- ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned++; \
+ ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned += (n); \
} while (0)
#define pgstat_count_buffer_read(s,r) \
do { \
- if (pgstat_collect_blocklevel && (s)->tabentry != NULL) \
- ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
- else { \
- if (pgstat_collect_blocklevel && !(s)->no_stats) { \
+ if (pgstat_collect_blocklevel) { \
+ if ((s)->tabentry != NULL) \
+ ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
+ else { \
pgstat_initstats((s), (r)); \
if ((s)->tabentry != NULL) \
((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
} while (0)
#define pgstat_count_buffer_hit(s,r) \
do { \
- if (pgstat_collect_blocklevel && (s)->tabentry != NULL) \
- ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
- else { \
- if (pgstat_collect_blocklevel && !(s)->no_stats) { \
+ if (pgstat_collect_blocklevel) { \
+ if ((s)->tabentry != NULL) \
+ ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
+ else { \
pgstat_initstats((s), (r)); \
if ((s)->tabentry != NULL) \
((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.85 2005/08/12 01:36:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.86 2005/10/06 02:29:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
typedef struct PgStat_Info
{
void *tabentry;
- bool no_stats;
- bool heap_scan_counted;
- bool index_scan_counted;
} PgStat_Info;
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") 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_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)))::bigint AS idx_scan, ((sum(pg_stat_get_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_tuples_fetched(c.oid)) 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_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") 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") OR (c.relkind = 't'::"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))))::bigint AS idx_blks_read, (sum(pg_stat_get_blocks_hit(i.indexrelid)))::bigint 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));
on
(1 row)
--- XXX stopgap until we figure out how bitmap scans should be counted
-SET enable_bitmapscan = off;
-- save counters
CREATE TEMP TABLE prevstats AS
SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch,
-- conditio sine qua non
SHOW stats_start_collector; -- must be on
--- XXX stopgap until we figure out how bitmap scans should be counted
-SET enable_bitmapscan = off;
-
-- save counters
CREATE TEMP TABLE prevstats AS
SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch,