Commit aec4cf1c authored by Tom Lane's avatar Tom Lane

Add a function pg_stat_clear_snapshot() that discards any statistics snapshot

already collected in the current transaction; this allows plpgsql functions to
watch for stats updates even though they are confined to a single transaction.
Use this instead of the previous kluge involving pg_stat_file() to wait for
the stats collector to update in the stats regression test.  Internally,
decouple storage of stats snapshots from transaction boundaries; they'll
now stick around until someone calls pgstat_clear_snapshot --- which xact.c
still does at transaction end, to maintain the previous behavior.  This makes
the logic a lot cleaner, at the price of a couple dozen cycles per transaction
exit.
parent d9ce6887
<!-- $PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.45 2007/02/01 00:28:17 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.46 2007/02/07 23:11:29 tgl Exp $ -->
<chapter id="monitoring">
<title>Monitoring Database Activity</title>
......@@ -227,7 +227,10 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
queries on the statistics and correlate the results without worrying that
the numbers are changing underneath you. But if you want to see new
results with each query, be sure to do the queries outside any transaction
block.
block. Alternatively, you can invoke
<function>pg_stat_clear_snapshot</function>(), which will discard the
current transaction's statistics snapshot (if any). The next use of
statistical information will cause a new snapshot to be fetched.
</para>
<table id="monitoring-stats-views-table">
......@@ -707,11 +710,20 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
</entry>
</row>
<row>
<entry><literal><function>pg_stat_clear_snapshot</function>()</literal></entry>
<entry><type>void</type></entry>
<entry>
Discard the current statistics snapshot
</entry>
</row>
<row>
<entry><literal><function>pg_stat_reset</function>()</literal></entry>
<entry><type>boolean</type></entry>
<entry><type>void</type></entry>
<entry>
Reset all block-level and row-level statistics to zero
Reset all statistics counters for the current database to zero
(requires superuser privileges)
</entry>
</row>
</tbody>
......
......@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.232 2007/02/01 19:10:25 momjian Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.233 2007/02/07 23:11:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1628,6 +1628,7 @@ CommitTransaction(void)
AtEOXact_Namespace(true);
/* smgrcommit already done */
AtEOXact_Files();
pgstat_clear_snapshot();
pgstat_count_xact_commit();
pgstat_report_txn_timestamp(0);
......@@ -1844,6 +1845,7 @@ PrepareTransaction(void)
AtEOXact_Namespace(true);
/* smgrcommit already done */
AtEOXact_Files();
pgstat_clear_snapshot();
CurrentResourceOwner = NULL;
ResourceOwnerDelete(TopTransactionResourceOwner);
......@@ -1995,6 +1997,7 @@ AbortTransaction(void)
AtEOXact_Namespace(false);
smgrabort();
AtEOXact_Files();
pgstat_clear_snapshot();
pgstat_count_xact_rollback();
pgstat_report_txn_timestamp(0);
......
......@@ -13,7 +13,7 @@
*
* Copyright (c) 2001-2007, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.144 2007/01/26 20:06:52 tgl Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.145 2007/02/07 23:11:29 tgl Exp $
* ----------
*/
#include "postgres.h"
......@@ -130,9 +130,8 @@ static TabStatArray SharedTabStat = {0, 0, NULL};
static int pgStatXactCommit = 0;
static int pgStatXactRollback = 0;
static TransactionId pgStatDBHashXact = InvalidTransactionId;
static MemoryContext pgStatLocalContext = NULL;
static HTAB *pgStatDBHash = NULL;
static TransactionId pgStatLocalStatusXact = InvalidTransactionId;
static PgBackendStatus *localBackendStatusTable = NULL;
static int localNumBackends = 0;
......@@ -156,11 +155,13 @@ static void pgstat_beshutdown_hook(int code, Datum arg);
static PgStat_StatDBEntry *pgstat_get_db_entry(Oid databaseid, bool create);
static void pgstat_drop_database(Oid databaseid);
static void pgstat_write_statsfile(void);
static void pgstat_read_statsfile(HTAB **dbhash, Oid onlydb);
static HTAB *pgstat_read_statsfile(Oid onlydb);
static void backend_read_statsfile(void);
static void pgstat_read_current_status(void);
static HTAB *pgstat_collect_oids(Oid catalogid);
static void pgstat_setup_memcxt(void);
static void pgstat_setheader(PgStat_MsgHdr *hdr, StatMsgType mtype);
static void pgstat_send(void *msg, int len);
......@@ -1535,22 +1536,24 @@ pgstat_report_waiting(bool waiting)
static void
pgstat_read_current_status(void)
{
TransactionId topXid = GetTopTransactionId();
volatile PgBackendStatus *beentry;
PgBackendStatus *localtable;
PgBackendStatus *localentry;
int i;
Assert(!pgStatRunningInCollector);
if (TransactionIdEquals(pgStatLocalStatusXact, topXid))
if (localBackendStatusTable)
return; /* already done */
localBackendStatusTable = (PgBackendStatus *)
MemoryContextAlloc(TopTransactionContext,
pgstat_setup_memcxt();
localtable = (PgBackendStatus *)
MemoryContextAlloc(pgStatLocalContext,
sizeof(PgBackendStatus) * MaxBackends);
localNumBackends = 0;
beentry = BackendStatusArray;
localentry = localBackendStatusTable;
localentry = localtable;
for (i = 1; i <= MaxBackends; i++)
{
/*
......@@ -1587,7 +1590,8 @@ pgstat_read_current_status(void)
}
}
pgStatLocalStatusXact = topXid;
/* Set the pointer only after completion of a valid table */
localBackendStatusTable = localtable;
}
......@@ -1720,7 +1724,7 @@ PgstatCollectorMain(int argc, char *argv[])
* zero.
*/
pgStatRunningInCollector = true;
pgstat_read_statsfile(&pgStatDBHash, InvalidOid);
pgStatDBHash = pgstat_read_statsfile(InvalidOid);
/*
* Setup the descriptor set for select(2). Since only one bit in the set
......@@ -2090,38 +2094,24 @@ pgstat_write_statsfile(void)
* databases' hash table (whose entries point to the tables' hash tables).
* ----------
*/
static void
pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
static HTAB *
pgstat_read_statsfile(Oid onlydb)
{
PgStat_StatDBEntry *dbentry;
PgStat_StatDBEntry dbbuf;
PgStat_StatTabEntry *tabentry;
PgStat_StatTabEntry tabbuf;
HASHCTL hash_ctl;
HTAB *dbhash;
HTAB *tabhash = NULL;
FILE *fpin;
int32 format_id;
bool found;
MemoryContext use_mcxt;
int mcxt_flags;
/*
* If running in the collector or the autovacuum process, we use the
* DynaHashCxt memory context. If running in a backend, we use the
* TopTransactionContext instead, so the caller must only know the last
* XactId when this call happened to know if his tables are still valid or
* already gone!
* The tables will live in pgStatLocalContext.
*/
if (pgStatRunningInCollector || IsAutoVacuumProcess())
{
use_mcxt = NULL;
mcxt_flags = 0;
}
else
{
use_mcxt = TopTransactionContext;
mcxt_flags = HASH_CONTEXT;
}
pgstat_setup_memcxt();
/*
* Create the DB hashtable
......@@ -2130,9 +2120,9 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(PgStat_StatDBEntry);
hash_ctl.hash = oid_hash;
hash_ctl.hcxt = use_mcxt;
*dbhash = hash_create("Databases hash", PGSTAT_DB_HASH_SIZE, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | mcxt_flags);
hash_ctl.hcxt = pgStatLocalContext;
dbhash = hash_create("Databases hash", PGSTAT_DB_HASH_SIZE, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
/*
* Try to open the status file. If it doesn't exist, the backends simply
......@@ -2140,7 +2130,7 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
* with empty counters.
*/
if ((fpin = AllocateFile(PGSTAT_STAT_FILENAME, PG_BINARY_R)) == NULL)
return;
return dbhash;
/*
* Verify it's of the expected format.
......@@ -2178,7 +2168,7 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
/*
* Add to the DB hash
*/
dbentry = (PgStat_StatDBEntry *) hash_search(*dbhash,
dbentry = (PgStat_StatDBEntry *) hash_search(dbhash,
(void *) &dbbuf.databaseid,
HASH_ENTER,
&found);
......@@ -2207,11 +2197,11 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
hash_ctl.hash = oid_hash;
hash_ctl.hcxt = use_mcxt;
hash_ctl.hcxt = pgStatLocalContext;
dbentry->tables = hash_create("Per-database table",
PGSTAT_TAB_HASH_SIZE,
&hash_ctl,
HASH_ELEM | HASH_FUNCTION | mcxt_flags);
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
/*
* Arrange that following 'T's add entries to this database's
......@@ -2274,44 +2264,78 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb)
done:
FreeFile(fpin);
return dbhash;
}
/*
* If not done for this transaction, read the statistics collector
* stats file into some hash tables.
*
* Because we store the tables in TopTransactionContext, the result
* is good for the entire current main transaction.
*
* Inside the autovacuum process, the statfile is assumed to be valid
* "forever", that is one iteration, within one database. This means
* we only consider the statistics as they were when the autovacuum
* iteration started.
* If not already done, read the statistics collector stats file into
* some hash tables. The results will be kept until pgstat_clear_snapshot()
* is called (typically, at end of transaction).
*/
static void
backend_read_statsfile(void)
{
/* already read it? */
if (pgStatDBHash)
return;
Assert(!pgStatRunningInCollector);
/* Autovacuum wants stats about all databases */
if (IsAutoVacuumProcess())
{
/* already read it? */
if (pgStatDBHash)
return;
Assert(!pgStatRunningInCollector);
pgstat_read_statsfile(&pgStatDBHash, InvalidOid);
}
pgStatDBHash = pgstat_read_statsfile(InvalidOid);
else
{
TransactionId topXid = GetTopTransactionId();
pgStatDBHash = pgstat_read_statsfile(MyDatabaseId);
}
if (!TransactionIdEquals(pgStatDBHashXact, topXid))
{
Assert(!pgStatRunningInCollector);
pgstat_read_statsfile(&pgStatDBHash, MyDatabaseId);
pgStatDBHashXact = topXid;
}
}
/* ----------
* pgstat_setup_memcxt() -
*
* Create pgStatLocalContext, if not already done.
* ----------
*/
static void
pgstat_setup_memcxt(void)
{
if (!pgStatLocalContext)
pgStatLocalContext = AllocSetContextCreate(TopMemoryContext,
"Statistics snapshot",
ALLOCSET_SMALL_MINSIZE,
ALLOCSET_SMALL_INITSIZE,
ALLOCSET_SMALL_MAXSIZE);
}
/* ----------
* pgstat_clear_snapshot() -
*
* Discard any data collected in the current transaction. Any subsequent
* request will cause new snapshots to be read.
*
* This is also invoked during transaction commit or abort to discard
* the no-longer-wanted snapshot.
* ----------
*/
void
pgstat_clear_snapshot(void)
{
/* In an autovacuum process we keep the stats forever */
if (IsAutoVacuumProcess())
return;
/* Release memory, if any was allocated */
if (pgStatLocalContext)
MemoryContextDelete(pgStatLocalContext);
/* Reset variables */
pgStatLocalContext = NULL;
pgStatDBHash = NULL;
localBackendStatusTable = NULL;
localNumBackends = 0;
}
/* ----------
* pgstat_recv_tabstat() -
*
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.37 2007/01/05 22:19:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.38 2007/02/07 23:11:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -39,7 +39,6 @@ extern Datum pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
......@@ -57,6 +56,9 @@ extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
extern Datum pg_stat_clear_snapshot(PG_FUNCTION_ARGS);
extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
Datum
pg_stat_get_numscans(PG_FUNCTION_ARGS)
......@@ -336,16 +338,6 @@ pg_backend_pid(PG_FUNCTION_ARGS)
PG_RETURN_INT32(MyProcPid);
}
/*
* Built-in function for resetting the counters
*/
Datum
pg_stat_reset(PG_FUNCTION_ARGS)
{
pgstat_reset_counters();
PG_RETURN_BOOL(true);
}
Datum
pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
......@@ -678,3 +670,23 @@ pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
PG_RETURN_INT64(result);
}
/* Discard the active statistics snapshot */
Datum
pg_stat_clear_snapshot(PG_FUNCTION_ARGS)
{
pgstat_clear_snapshot();
PG_RETURN_VOID();
}
/* Reset all counters for the current database */
Datum
pg_stat_reset(PG_FUNCTION_ARGS)
{
pgstat_reset_counters();
PG_RETURN_VOID();
}
......@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.381 2007/02/06 02:59:12 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.382 2007/02/07 23:11:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200702051
#define CATALOG_VERSION_NO 200702071
#endif
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.442 2007/02/03 14:06:55 petere Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.443 2007/02/07 23:11:30 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -2938,8 +2938,6 @@ DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 f f t
DESCR("Statistics: Currently active backend IDs");
DATA(insert OID = 2026 ( pg_backend_pid PGNSP PGUID 12 1 0 f f t f s 0 23 "" _null_ _null_ _null_ pg_backend_pid - _null_ ));
DESCR("Statistics: Current backend PID");
DATA(insert OID = 2274 ( pg_stat_reset PGNSP PGUID 12 1 0 f f f f v 0 16 "" _null_ _null_ _null_ pg_stat_reset - _null_ ));
DESCR("Statistics: Reset collected statistics");
DATA(insert OID = 1937 ( pg_stat_get_backend_pid PGNSP PGUID 12 1 0 f f t f s 1 23 "23" _null_ _null_ _null_ pg_stat_get_backend_pid - _null_ ));
DESCR("Statistics: PID of backend");
DATA(insert OID = 1938 ( pg_stat_get_backend_dbid PGNSP PGUID 12 1 0 f f t f s 1 26 "23" _null_ _null_ _null_ pg_stat_get_backend_dbid - _null_ ));
......@@ -2970,6 +2968,10 @@ DATA(insert OID = 1944 ( pg_stat_get_db_blocks_fetched PGNSP PGUID 12 1 0 f f t
DESCR("Statistics: Blocks fetched for database");
DATA(insert OID = 1945 ( pg_stat_get_db_blocks_hit PGNSP PGUID 12 1 0 f f t f s 1 20 "26" _null_ _null_ _null_ pg_stat_get_db_blocks_hit - _null_ ));
DESCR("Statistics: Blocks found in cache for database");
DATA(insert OID = 2230 ( pg_stat_clear_snapshot PGNSP PGUID 12 1 0 f f f f v 0 2278 "" _null_ _null_ _null_ pg_stat_clear_snapshot - _null_ ));
DESCR("Statistics: Discard current transaction's statistics snapshot");
DATA(insert OID = 2274 ( pg_stat_reset PGNSP PGUID 12 1 0 f f f f v 0 2278 "" _null_ _null_ _null_ pg_stat_reset - _null_ ));
DESCR("Statistics: Reset collected statistics for current database");
DATA(insert OID = 1946 ( encode PGNSP PGUID 12 1 0 f f t f i 2 25 "17 25" _null_ _null_ _null_ binary_encode - _null_ ));
DESCR("Convert bytea value into some ascii-only text string");
......
......@@ -5,7 +5,7 @@
*
* Copyright (c) 2001-2007, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.52 2007/01/05 22:19:50 momjian Exp $
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.53 2007/02/07 23:11:30 tgl Exp $
* ----------
*/
#ifndef PGSTAT_H
......@@ -380,6 +380,7 @@ extern void pgstat_report_tabstat(void);
extern void pgstat_vacuum_tabstat(void);
extern void pgstat_drop_relation(Oid relid);
extern void pgstat_clear_snapshot(void);
extern void pgstat_reset_counters(void);
extern void pgstat_report_autovac(Oid dboid);
......
......@@ -27,61 +27,28 @@ SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch,
FROM pg_catalog.pg_stat_user_tables AS t,
pg_catalog.pg_statio_user_tables AS b
WHERE t.relname='tenk2' AND b.relname='tenk2';
-- enable statistics
SET stats_block_level = on;
SET stats_row_level = on;
-- do a seqscan
SELECT count(*) FROM tenk2;
count
-------
10000
(1 row)
-- do an indexscan
SELECT count(*) FROM tenk2 WHERE unique1 = 1;
count
-------
1
(1 row)
-- All of the thrashing here is to wait for the stats collector to update,
-- without waiting too long (in fact, we'd like to try to measure how long
-- we wait). Watching for change in the stats themselves wouldn't work
-- because the backend only reads them once per transaction. The stats file
-- mod timestamp isn't too helpful because it may have resolution of only one
-- second, or even worse. So, we touch a new table and then watch for change
-- in the size of the stats file. Ugh.
-- save current stats-file size
CREATE TEMP TABLE prevfilesize AS
SELECT size FROM pg_stat_file('global/pgstat.stat');
-- make and touch a previously nonexistent table
CREATE TABLE stats_hack (f1 int);
SELECT * FROM stats_hack;
f1
----
(0 rows)
-- wait for stats collector to update
-- function to wait for counters to advance
create function wait_for_stats() returns void as $$
declare
start_time timestamptz := clock_timestamp();
oldsize bigint;
newsize bigint;
updated bool;
begin
-- fetch previous stats-file size
select size into oldsize from prevfilesize;
-- we don't want to wait forever; loop will exit after 30 seconds
for i in 1 .. 300 loop
-- look for update of stats file
select size into newsize from pg_stat_file('global/pgstat.stat');
-- check to see if indexscan has been sensed
SELECT (st.idx_scan >= pr.idx_scan + 1) INTO updated
FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
exit when newsize != oldsize;
exit when updated;
-- wait a little
perform pg_sleep(0.1);
-- reset stats snapshot so we can test again
perform pg_stat_clear_snapshot();
end loop;
-- report time waited in postmaster log (where it won't change test output)
......@@ -89,13 +56,30 @@ begin
extract(epoch from clock_timestamp() - start_time);
end
$$ language plpgsql;
-- enable statistics
SET stats_block_level = on;
SET stats_row_level = on;
-- do a seqscan
SELECT count(*) FROM tenk2;
count
-------
10000
(1 row)
-- do an indexscan
SELECT count(*) FROM tenk2 WHERE unique1 = 1;
count
-------
1
(1 row)
-- wait for stats collector to update
SELECT wait_for_stats();
wait_for_stats
----------------
(1 row)
DROP TABLE stats_hack;
-- check effects
SELECT st.seq_scan >= pr.seq_scan + 1,
st.seq_tup_read >= pr.seq_tup_read + cl.reltuples,
......
......@@ -21,52 +21,28 @@ SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch,
pg_catalog.pg_statio_user_tables AS b
WHERE t.relname='tenk2' AND b.relname='tenk2';
-- enable statistics
SET stats_block_level = on;
SET stats_row_level = on;
-- do a seqscan
SELECT count(*) FROM tenk2;
-- do an indexscan
SELECT count(*) FROM tenk2 WHERE unique1 = 1;
-- All of the thrashing here is to wait for the stats collector to update,
-- without waiting too long (in fact, we'd like to try to measure how long
-- we wait). Watching for change in the stats themselves wouldn't work
-- because the backend only reads them once per transaction. The stats file
-- mod timestamp isn't too helpful because it may have resolution of only one
-- second, or even worse. So, we touch a new table and then watch for change
-- in the size of the stats file. Ugh.
-- save current stats-file size
CREATE TEMP TABLE prevfilesize AS
SELECT size FROM pg_stat_file('global/pgstat.stat');
-- make and touch a previously nonexistent table
CREATE TABLE stats_hack (f1 int);
SELECT * FROM stats_hack;
-- wait for stats collector to update
-- function to wait for counters to advance
create function wait_for_stats() returns void as $$
declare
start_time timestamptz := clock_timestamp();
oldsize bigint;
newsize bigint;
updated bool;
begin
-- fetch previous stats-file size
select size into oldsize from prevfilesize;
-- we don't want to wait forever; loop will exit after 30 seconds
for i in 1 .. 300 loop
-- look for update of stats file
select size into newsize from pg_stat_file('global/pgstat.stat');
-- check to see if indexscan has been sensed
SELECT (st.idx_scan >= pr.idx_scan + 1) INTO updated
FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
exit when newsize != oldsize;
exit when updated;
-- wait a little
perform pg_sleep(0.1);
-- reset stats snapshot so we can test again
perform pg_stat_clear_snapshot();
end loop;
-- report time waited in postmaster log (where it won't change test output)
......@@ -75,9 +51,17 @@ begin
end
$$ language plpgsql;
SELECT wait_for_stats();
-- enable statistics
SET stats_block_level = on;
SET stats_row_level = on;
DROP TABLE stats_hack;
-- do a seqscan
SELECT count(*) FROM tenk2;
-- do an indexscan
SELECT count(*) FROM tenk2 WHERE unique1 = 1;
-- wait for stats collector to update
SELECT wait_for_stats();
-- check effects
SELECT st.seq_scan >= pr.seq_scan + 1,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment