@@ -30,26 +30,72 @@ SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch,
30
30
-- enable statistics
31
31
SET stats_block_level = on;
32
32
SET stats_row_level = on;
33
- -- do something
33
+ -- do a seqscan
34
34
SELECT count(*) FROM tenk2;
35
35
count
36
36
-------
37
37
10000
38
38
(1 row)
39
39
40
+ -- do an indexscan
40
41
SELECT count(*) FROM tenk2 WHERE unique1 = 1;
41
42
count
42
43
-------
43
44
1
44
45
(1 row)
45
46
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
+ ----------------
50
95
51
96
(1 row)
52
97
98
+ DROP TABLE stats_hack;
53
99
-- check effects
54
100
SELECT st.seq_scan >= pr.seq_scan + 1,
55
101
st.seq_tup_read >= pr.seq_tup_read + cl.reltuples,
0 commit comments