Thread: Regression test for stats collector
With pg_autovacuum becoming increasingly popular it's important to have a working stats collector. This test is able to discover the problem that was present in 7.4 Beta 2. Servus Manfred diff -ruN ../base/src/test/regress/expected/stats.out src/test/regress/expected/stats.out --- ../base/src/test/regress/expected/stats.out 1970-01-01 01:00:00.000000000 +0100 +++ src/test/regress/expected/stats.out 2003-09-10 21:01:49.000000000 +0200 @@ -0,0 +1,79 @@ +-- +-- Test Statistics Collector +-- +-- Must be run after tenk2 has been created (by create_table), +-- populated (by create_misc) and indexed (by create_index). +-- +-- conditio sine qua non +SHOW stats_start_collector; -- must be on + stats_start_collector +----------------------- + on +(1 row) + +-- save counters +CREATE TEMP TABLE prevstats AS +SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch, + (b.heap_blks_read + b.heap_blks_hit) AS heap_blks, + (b.idx_blks_read + b.idx_blks_hit) AS idx_blks + 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; +-- helper function +CREATE FUNCTION sleep(interval) RETURNS integer AS ' +DECLARE + endtime timestamp; +BEGIN + endtime := timeofday()::timestamp + $1; + WHILE timeofday()::timestamp < endtime LOOP + END LOOP; + RETURN 0; +END; +' LANGUAGE 'plpgsql'; +-- do something +SELECT count(*) FROM tenk2; + count +------- + 10000 +(1 row) + +SELECT count(*) FROM tenk2 WHERE unique1 = 1; + count +------- + 1 +(1 row) + +-- let stats collector catch up +SELECT sleep('0:0:2'::interval); + sleep +------- + 0 +(1 row) + +-- check effects +SELECT st.seq_scan >= pr.seq_scan + 1, + st.seq_tup_read >= pr.seq_tup_read + cl.reltuples, + st.idx_scan >= pr.idx_scan + 1, + st.idx_tup_fetch >= pr.idx_tup_fetch + 1 + FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr + WHERE st.relname='tenk2' AND cl.relname='tenk2'; + ?column? | ?column? | ?column? | ?column? +----------+----------+----------+---------- + t | t | t | t +(1 row) + +SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + cl.relpages, + st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1 + FROM pg_statio_user_tables AS st, pg_class AS cl, prevstats AS pr + WHERE st.relname='tenk2' AND cl.relname='tenk2'; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +-- clean up +DROP FUNCTION sleep(interval); +-- End of Stats Test diff -ruN ../base/src/test/regress/parallel_schedule src/test/regress/parallel_schedule --- ../base/src/test/regress/parallel_schedule 2003-09-02 20:48:55.000000000 +0200 +++ src/test/regress/parallel_schedule 2003-09-10 21:02:40.000000000 +0200 @@ -74,4 +74,4 @@ # The sixth group of parallel test # ---------- # "plpgsql" cannot run concurrently with "rules" -test: limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphism +test: limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphismstats diff -ruN ../base/src/test/regress/serial_schedule src/test/regress/serial_schedule --- ../base/src/test/regress/serial_schedule 2003-09-02 20:48:55.000000000 +0200 +++ src/test/regress/serial_schedule 2003-09-10 21:03:16.000000000 +0200 @@ -94,3 +94,4 @@ test: alter_table test: sequence test: polymorphism +test: stats diff -ruN ../base/src/test/regress/sql/stats.sql src/test/regress/sql/stats.sql --- ../base/src/test/regress/sql/stats.sql 1970-01-01 01:00:00.000000000 +0100 +++ src/test/regress/sql/stats.sql 2003-09-10 21:01:49.000000000 +0200 @@ -0,0 +1,58 @@ +-- +-- Test Statistics Collector +-- +-- Must be run after tenk2 has been created (by create_table), +-- populated (by create_misc) and indexed (by create_index). +-- + +-- conditio sine qua non +SHOW stats_start_collector; -- must be on + +-- save counters +CREATE TEMP TABLE prevstats AS +SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch, + (b.heap_blks_read + b.heap_blks_hit) AS heap_blks, + (b.idx_blks_read + b.idx_blks_hit) AS idx_blks + 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; + +-- helper function +CREATE FUNCTION sleep(interval) RETURNS integer AS ' +DECLARE + endtime timestamp; +BEGIN + endtime := timeofday()::timestamp + $1; + WHILE timeofday()::timestamp < endtime LOOP + END LOOP; + RETURN 0; +END; +' LANGUAGE 'plpgsql'; + +-- do something +SELECT count(*) FROM tenk2; +SELECT count(*) FROM tenk2 WHERE unique1 = 1; + +-- let stats collector catch up +SELECT sleep('0:0:2'::interval); + +-- check effects +SELECT st.seq_scan >= pr.seq_scan + 1, + st.seq_tup_read >= pr.seq_tup_read + cl.reltuples, + st.idx_scan >= pr.idx_scan + 1, + st.idx_tup_fetch >= pr.idx_tup_fetch + 1 + FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr + WHERE st.relname='tenk2' AND cl.relname='tenk2'; +SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + cl.relpages, + st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1 + FROM pg_statio_user_tables AS st, pg_class AS cl, prevstats AS pr + WHERE st.relname='tenk2' AND cl.relname='tenk2'; + +-- clean up +DROP FUNCTION sleep(interval); + +-- End of Stats Test
Uh, how do you force the stats collector to 'on' before the test is run? --------------------------------------------------------------------------- Manfred Koizar wrote: > With pg_autovacuum becoming increasingly popular it's important to > have a working stats collector. This test is able to discover the > problem that was present in 7.4 Beta 2. > > Servus > Manfred > diff -ruN ../base/src/test/regress/expected/stats.out src/test/regress/expected/stats.out > --- ../base/src/test/regress/expected/stats.out 1970-01-01 01:00:00.000000000 +0100 > +++ src/test/regress/expected/stats.out 2003-09-10 21:01:49.000000000 +0200 > @@ -0,0 +1,79 @@ > +-- > +-- Test Statistics Collector > +-- > +-- Must be run after tenk2 has been created (by create_table), > +-- populated (by create_misc) and indexed (by create_index). > +-- > +-- conditio sine qua non > +SHOW stats_start_collector; -- must be on > + stats_start_collector > +----------------------- > + on > +(1 row) > + > +-- save counters > +CREATE TEMP TABLE prevstats AS > +SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch, > + (b.heap_blks_read + b.heap_blks_hit) AS heap_blks, > + (b.idx_blks_read + b.idx_blks_hit) AS idx_blks > + 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; > +-- helper function > +CREATE FUNCTION sleep(interval) RETURNS integer AS ' > +DECLARE > + endtime timestamp; > +BEGIN > + endtime := timeofday()::timestamp + $1; > + WHILE timeofday()::timestamp < endtime LOOP > + END LOOP; > + RETURN 0; > +END; > +' LANGUAGE 'plpgsql'; > +-- do something > +SELECT count(*) FROM tenk2; > + count > +------- > + 10000 > +(1 row) > + > +SELECT count(*) FROM tenk2 WHERE unique1 = 1; > + count > +------- > + 1 > +(1 row) > + > +-- let stats collector catch up > +SELECT sleep('0:0:2'::interval); > + sleep > +------- > + 0 > +(1 row) > + > +-- check effects > +SELECT st.seq_scan >= pr.seq_scan + 1, > + st.seq_tup_read >= pr.seq_tup_read + cl.reltuples, > + st.idx_scan >= pr.idx_scan + 1, > + st.idx_tup_fetch >= pr.idx_tup_fetch + 1 > + FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr > + WHERE st.relname='tenk2' AND cl.relname='tenk2'; > + ?column? | ?column? | ?column? | ?column? > +----------+----------+----------+---------- > + t | t | t | t > +(1 row) > + > +SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + cl.relpages, > + st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1 > + FROM pg_statio_user_tables AS st, pg_class AS cl, prevstats AS pr > + WHERE st.relname='tenk2' AND cl.relname='tenk2'; > + ?column? | ?column? > +----------+---------- > + t | t > +(1 row) > + > +-- clean up > +DROP FUNCTION sleep(interval); > +-- End of Stats Test > diff -ruN ../base/src/test/regress/parallel_schedule src/test/regress/parallel_schedule > --- ../base/src/test/regress/parallel_schedule 2003-09-02 20:48:55.000000000 +0200 > +++ src/test/regress/parallel_schedule 2003-09-10 21:02:40.000000000 +0200 > @@ -74,4 +74,4 @@ > # The sixth group of parallel test > # ---------- > # "plpgsql" cannot run concurrently with "rules" > -test: limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphism > +test: limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphismstats > diff -ruN ../base/src/test/regress/serial_schedule src/test/regress/serial_schedule > --- ../base/src/test/regress/serial_schedule 2003-09-02 20:48:55.000000000 +0200 > +++ src/test/regress/serial_schedule 2003-09-10 21:03:16.000000000 +0200 > @@ -94,3 +94,4 @@ > test: alter_table > test: sequence > test: polymorphism > +test: stats > diff -ruN ../base/src/test/regress/sql/stats.sql src/test/regress/sql/stats.sql > --- ../base/src/test/regress/sql/stats.sql 1970-01-01 01:00:00.000000000 +0100 > +++ src/test/regress/sql/stats.sql 2003-09-10 21:01:49.000000000 +0200 > @@ -0,0 +1,58 @@ > +-- > +-- Test Statistics Collector > +-- > +-- Must be run after tenk2 has been created (by create_table), > +-- populated (by create_misc) and indexed (by create_index). > +-- > + > +-- conditio sine qua non > +SHOW stats_start_collector; -- must be on > + > +-- save counters > +CREATE TEMP TABLE prevstats AS > +SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch, > + (b.heap_blks_read + b.heap_blks_hit) AS heap_blks, > + (b.idx_blks_read + b.idx_blks_hit) AS idx_blks > + 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; > + > +-- helper function > +CREATE FUNCTION sleep(interval) RETURNS integer AS ' > +DECLARE > + endtime timestamp; > +BEGIN > + endtime := timeofday()::timestamp + $1; > + WHILE timeofday()::timestamp < endtime LOOP > + END LOOP; > + RETURN 0; > +END; > +' LANGUAGE 'plpgsql'; > + > +-- do something > +SELECT count(*) FROM tenk2; > +SELECT count(*) FROM tenk2 WHERE unique1 = 1; > + > +-- let stats collector catch up > +SELECT sleep('0:0:2'::interval); > + > +-- check effects > +SELECT st.seq_scan >= pr.seq_scan + 1, > + st.seq_tup_read >= pr.seq_tup_read + cl.reltuples, > + st.idx_scan >= pr.idx_scan + 1, > + st.idx_tup_fetch >= pr.idx_tup_fetch + 1 > + FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr > + WHERE st.relname='tenk2' AND cl.relname='tenk2'; > +SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + cl.relpages, > + st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1 > + FROM pg_statio_user_tables AS st, pg_class AS cl, prevstats AS pr > + WHERE st.relname='tenk2' AND cl.relname='tenk2'; > + > +-- clean up > +DROP FUNCTION sleep(interval); > + > +-- End of Stats Test > > ---------------------------(end of broadcast)--------------------------- > TIP 3: if posting/reading through Usenet, please send an appropriate > subscribe-nomail command to majordomo@postgresql.org so that your > message can get through to the mailing list cleanly -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
On Thu, 2003-09-11 at 11:58, Bruce Momjian wrote: > Uh, how do you force the stats collector to 'on' before the test is > run? The stats collector is on by default (of course, that doesn't apply to "make installcheck"...) But this reminds me: I think it would be cool to extend the language we use for writing regression tests to be more than mere SQL. We could do with boolean expressions ("IF stats_collector_is_on THEN run_test ELSE skip_test"), better control over parallel regression tests ("Run all possible interleavings of tests X, Y, and Z"; "Run X and Y simultaneously"; etc.), and more. -Neil
Neil Conway wrote: > On Thu, 2003-09-11 at 11:58, Bruce Momjian wrote: > > Uh, how do you force the stats collector to 'on' before the test is > > run? > > The stats collector is on by default (of course, that doesn't apply to > "make installcheck"...) Oh I see now, nice. I didn't realize you could turn it on per backend. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
On Thu, 11 Sep 2003 23:17:13 -0400 (EDT), Bruce Momjian <pgman@candle.pha.pa.us> wrote: >> The stats collector is on by default (of course, that doesn't apply to >> "make installcheck"...) By doing "appropriate" changes to your installation I guess you can break almost every test ;-) >Oh I see now, nice. I didn't realize you could turn it on per backend. stats_start_collector and stats_reset_on_server_start "cannot be changed after server start". stats_command_string, stats_block_level, and stats_row_level can be set per backend. The test starts with +SHOW stats_start_collector; -- must be on + stats_start_collector +----------------------- + on +(1 row) so that, if the test fails, you can look at the diff and have a chance to tell whether the stats collector is not activated or not working properly. BTW, the test succeeds on 7.3.4, but the patch won't apply cleanly. If anybody is interested, the patch for 7.3.4 can be fetched from http://www.pivot.at/pg/25-TestStats_734.diff . Servus Manfred
Patch applied. Thanks. --------------------------------------------------------------------------- Manfred Koizar wrote: > With pg_autovacuum becoming increasingly popular it's important to > have a working stats collector. This test is able to discover the > problem that was present in 7.4 Beta 2. > > Servus > Manfred > diff -ruN ../base/src/test/regress/expected/stats.out src/test/regress/expected/stats.out > --- ../base/src/test/regress/expected/stats.out 1970-01-01 01:00:00.000000000 +0100 > +++ src/test/regress/expected/stats.out 2003-09-10 21:01:49.000000000 +0200 > @@ -0,0 +1,79 @@ > +-- > +-- Test Statistics Collector > +-- > +-- Must be run after tenk2 has been created (by create_table), > +-- populated (by create_misc) and indexed (by create_index). > +-- > +-- conditio sine qua non > +SHOW stats_start_collector; -- must be on > + stats_start_collector > +----------------------- > + on > +(1 row) > + > +-- save counters > +CREATE TEMP TABLE prevstats AS > +SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch, > + (b.heap_blks_read + b.heap_blks_hit) AS heap_blks, > + (b.idx_blks_read + b.idx_blks_hit) AS idx_blks > + 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; > +-- helper function > +CREATE FUNCTION sleep(interval) RETURNS integer AS ' > +DECLARE > + endtime timestamp; > +BEGIN > + endtime := timeofday()::timestamp + $1; > + WHILE timeofday()::timestamp < endtime LOOP > + END LOOP; > + RETURN 0; > +END; > +' LANGUAGE 'plpgsql'; > +-- do something > +SELECT count(*) FROM tenk2; > + count > +------- > + 10000 > +(1 row) > + > +SELECT count(*) FROM tenk2 WHERE unique1 = 1; > + count > +------- > + 1 > +(1 row) > + > +-- let stats collector catch up > +SELECT sleep('0:0:2'::interval); > + sleep > +------- > + 0 > +(1 row) > + > +-- check effects > +SELECT st.seq_scan >= pr.seq_scan + 1, > + st.seq_tup_read >= pr.seq_tup_read + cl.reltuples, > + st.idx_scan >= pr.idx_scan + 1, > + st.idx_tup_fetch >= pr.idx_tup_fetch + 1 > + FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr > + WHERE st.relname='tenk2' AND cl.relname='tenk2'; > + ?column? | ?column? | ?column? | ?column? > +----------+----------+----------+---------- > + t | t | t | t > +(1 row) > + > +SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + cl.relpages, > + st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1 > + FROM pg_statio_user_tables AS st, pg_class AS cl, prevstats AS pr > + WHERE st.relname='tenk2' AND cl.relname='tenk2'; > + ?column? | ?column? > +----------+---------- > + t | t > +(1 row) > + > +-- clean up > +DROP FUNCTION sleep(interval); > +-- End of Stats Test > diff -ruN ../base/src/test/regress/parallel_schedule src/test/regress/parallel_schedule > --- ../base/src/test/regress/parallel_schedule 2003-09-02 20:48:55.000000000 +0200 > +++ src/test/regress/parallel_schedule 2003-09-10 21:02:40.000000000 +0200 > @@ -74,4 +74,4 @@ > # The sixth group of parallel test > # ---------- > # "plpgsql" cannot run concurrently with "rules" > -test: limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphism > +test: limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphismstats > diff -ruN ../base/src/test/regress/serial_schedule src/test/regress/serial_schedule > --- ../base/src/test/regress/serial_schedule 2003-09-02 20:48:55.000000000 +0200 > +++ src/test/regress/serial_schedule 2003-09-10 21:03:16.000000000 +0200 > @@ -94,3 +94,4 @@ > test: alter_table > test: sequence > test: polymorphism > +test: stats > diff -ruN ../base/src/test/regress/sql/stats.sql src/test/regress/sql/stats.sql > --- ../base/src/test/regress/sql/stats.sql 1970-01-01 01:00:00.000000000 +0100 > +++ src/test/regress/sql/stats.sql 2003-09-10 21:01:49.000000000 +0200 > @@ -0,0 +1,58 @@ > +-- > +-- Test Statistics Collector > +-- > +-- Must be run after tenk2 has been created (by create_table), > +-- populated (by create_misc) and indexed (by create_index). > +-- > + > +-- conditio sine qua non > +SHOW stats_start_collector; -- must be on > + > +-- save counters > +CREATE TEMP TABLE prevstats AS > +SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch, > + (b.heap_blks_read + b.heap_blks_hit) AS heap_blks, > + (b.idx_blks_read + b.idx_blks_hit) AS idx_blks > + 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; > + > +-- helper function > +CREATE FUNCTION sleep(interval) RETURNS integer AS ' > +DECLARE > + endtime timestamp; > +BEGIN > + endtime := timeofday()::timestamp + $1; > + WHILE timeofday()::timestamp < endtime LOOP > + END LOOP; > + RETURN 0; > +END; > +' LANGUAGE 'plpgsql'; > + > +-- do something > +SELECT count(*) FROM tenk2; > +SELECT count(*) FROM tenk2 WHERE unique1 = 1; > + > +-- let stats collector catch up > +SELECT sleep('0:0:2'::interval); > + > +-- check effects > +SELECT st.seq_scan >= pr.seq_scan + 1, > + st.seq_tup_read >= pr.seq_tup_read + cl.reltuples, > + st.idx_scan >= pr.idx_scan + 1, > + st.idx_tup_fetch >= pr.idx_tup_fetch + 1 > + FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr > + WHERE st.relname='tenk2' AND cl.relname='tenk2'; > +SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + cl.relpages, > + st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1 > + FROM pg_statio_user_tables AS st, pg_class AS cl, prevstats AS pr > + WHERE st.relname='tenk2' AND cl.relname='tenk2'; > + > +-- clean up > +DROP FUNCTION sleep(interval); > + > +-- End of Stats Test > > ---------------------------(end of broadcast)--------------------------- > TIP 3: if posting/reading through Usenet, please send an appropriate > subscribe-nomail command to majordomo@postgresql.org so that your > message can get through to the mailing list cleanly -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073