Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d9ce688

Browse files
committed
Modify the stats regression test to delay until the stats file actually
changes (with an upper limit of 30 seconds), and record the delay time in the postmaster log. This should give us some info about what's happening with the intermittent stats failures in buildfarm. After an idea of Andrew Dunstan's.
1 parent 78d1216 commit d9ce688

File tree

2 files changed

+101
-8
lines changed

2 files changed

+101
-8
lines changed

src/test/regress/expected/stats.out

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,72 @@ SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch,
3030
-- enable statistics
3131
SET stats_block_level = on;
3232
SET stats_row_level = on;
33-
-- do something
33+
-- do a seqscan
3434
SELECT count(*) FROM tenk2;
3535
count
3636
-------
3737
10000
3838
(1 row)
3939

40+
-- do an indexscan
4041
SELECT count(*) FROM tenk2 WHERE unique1 = 1;
4142
count
4243
-------
4344
1
4445
(1 row)
4546

46-
-- let stats collector catch up
47-
SELECT pg_sleep(2.0);
48-
pg_sleep
49-
----------
47+
-- All of the thrashing here is to wait for the stats collector to update,
48+
-- without waiting too long (in fact, we'd like to try to measure how long
49+
-- we wait). Watching for change in the stats themselves wouldn't work
50+
-- because the backend only reads them once per transaction. The stats file
51+
-- mod timestamp isn't too helpful because it may have resolution of only one
52+
-- second, or even worse. So, we touch a new table and then watch for change
53+
-- in the size of the stats file. Ugh.
54+
-- save current stats-file size
55+
CREATE TEMP TABLE prevfilesize AS
56+
SELECT size FROM pg_stat_file('global/pgstat.stat');
57+
-- make and touch a previously nonexistent table
58+
CREATE TABLE stats_hack (f1 int);
59+
SELECT * FROM stats_hack;
60+
f1
61+
----
62+
(0 rows)
63+
64+
-- wait for stats collector to update
65+
create function wait_for_stats() returns void as $$
66+
declare
67+
start_time timestamptz := clock_timestamp();
68+
oldsize bigint;
69+
newsize bigint;
70+
begin
71+
-- fetch previous stats-file size
72+
select size into oldsize from prevfilesize;
73+
74+
-- we don't want to wait forever; loop will exit after 30 seconds
75+
for i in 1 .. 300 loop
76+
77+
-- look for update of stats file
78+
select size into newsize from pg_stat_file('global/pgstat.stat');
79+
80+
exit when newsize != oldsize;
81+
82+
-- wait a little
83+
perform pg_sleep(0.1);
84+
85+
end loop;
86+
87+
-- report time waited in postmaster log (where it won't change test output)
88+
raise log 'wait_for_stats delayed % seconds',
89+
extract(epoch from clock_timestamp() - start_time);
90+
end
91+
$$ language plpgsql;
92+
SELECT wait_for_stats();
93+
wait_for_stats
94+
----------------
5095

5196
(1 row)
5297

98+
DROP TABLE stats_hack;
5399
-- check effects
54100
SELECT st.seq_scan >= pr.seq_scan + 1,
55101
st.seq_tup_read >= pr.seq_tup_read + cl.reltuples,

src/test/regress/sql/stats.sql

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,59 @@ SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch,
2525
SET stats_block_level = on;
2626
SET stats_row_level = on;
2727

28-
-- do something
28+
-- do a seqscan
2929
SELECT count(*) FROM tenk2;
30+
-- do an indexscan
3031
SELECT count(*) FROM tenk2 WHERE unique1 = 1;
3132

32-
-- let stats collector catch up
33-
SELECT pg_sleep(2.0);
33+
-- All of the thrashing here is to wait for the stats collector to update,
34+
-- without waiting too long (in fact, we'd like to try to measure how long
35+
-- we wait). Watching for change in the stats themselves wouldn't work
36+
-- because the backend only reads them once per transaction. The stats file
37+
-- mod timestamp isn't too helpful because it may have resolution of only one
38+
-- second, or even worse. So, we touch a new table and then watch for change
39+
-- in the size of the stats file. Ugh.
40+
41+
-- save current stats-file size
42+
CREATE TEMP TABLE prevfilesize AS
43+
SELECT size FROM pg_stat_file('global/pgstat.stat');
44+
45+
-- make and touch a previously nonexistent table
46+
CREATE TABLE stats_hack (f1 int);
47+
SELECT * FROM stats_hack;
48+
49+
-- wait for stats collector to update
50+
create function wait_for_stats() returns void as $$
51+
declare
52+
start_time timestamptz := clock_timestamp();
53+
oldsize bigint;
54+
newsize bigint;
55+
begin
56+
-- fetch previous stats-file size
57+
select size into oldsize from prevfilesize;
58+
59+
-- we don't want to wait forever; loop will exit after 30 seconds
60+
for i in 1 .. 300 loop
61+
62+
-- look for update of stats file
63+
select size into newsize from pg_stat_file('global/pgstat.stat');
64+
65+
exit when newsize != oldsize;
66+
67+
-- wait a little
68+
perform pg_sleep(0.1);
69+
70+
end loop;
71+
72+
-- report time waited in postmaster log (where it won't change test output)
73+
raise log 'wait_for_stats delayed % seconds',
74+
extract(epoch from clock_timestamp() - start_time);
75+
end
76+
$$ language plpgsql;
77+
78+
SELECT wait_for_stats();
79+
80+
DROP TABLE stats_hack;
3481

3582
-- check effects
3683
SELECT st.seq_scan >= pr.seq_scan + 1,

0 commit comments

Comments
 (0)