On 02/25/2013 09:00 AM, Alban Hertroys
wrote:
1 update = 1 insert + 1 delete cancel each other out with respect to pg_stat_user_tables.n_live_tup. Naturally, they dont't cancel each other out with pg_stat_user_tables.n_tup_ins or n_tup_del - they don't even show up in those values, presumably because that's what n_tup_upd is there for. However the update adds to n_dead_tup. VACUUM does not reset *any* of the statistics values that can be accessed via pg_stat_user_tables, apart from n_dead_tup (hopefully ;-) Anyway, to estimate the autoanalyze trigger, I would need statistics that get reset by autoanalyze not autovacuum. I wrote a test script to show the behaviour. Be sure to wait a second each time before accessing pg_stat_user_tables as there is a delay in getting those data: CREATE TABLE test_stat (id BIGINT, some_number BIGINT); INSERT INTO test_stat (SELECT generate_series(1,10000) AS i, random() AS r); SELECT count(*) FROM test_stat; ANALYZE test_stat; -- wait here (0.5 s) for statistics collector to catch up SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; INSERT INTO test_stat (SELECT generate_series(10001,10900) AS i, random() AS r); -- wait here (0.5 s) for statistics collector to catch up SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; DELETE FROM test_stat WHERE id > 10000; -- wait here (0.5 s) for statistics collector to catch up SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; UPDATE test_stat set some_number = 1 where id > 9100; -- wait here (0.5 s) for statistics collector to catch up SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; ANALYZE test_stat; SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; VACUUM test_stat; -- wait here (0.5 s) for statistics collector to catch up SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; DROP TABLE test_stat; Output from a postgres 9.2 database: -------------------------------------------------- test=# CREATE TABLE test_stat (id BIGINT, some_number BIGINT); CREATE TABLE test=# INSERT INTO test_stat (SELECT generate_series(1,10000) AS i, random() AS r); INSERT 0 10000 test=# SELECT count(*) FROM test_stat; count ------- 10000 (1 row) test=# ANALYZE test_stat; ANALYZE test=# SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; relname | reltuples -----------+----------- test_stat | 10000 (1 row) test=# SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; relname | n_live_tup | n_dead_tup | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd -----------+------------+------------+-----------+-----------+-----------+--------------- test_stat | 10000 | 0 | 10000 | 0 | 0 | 0 (1 row) test=# INSERT INTO test_stat (SELECT generate_series(10001,10900) AS i, random() AS r); INSERT 0 900 test=# SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; relname | reltuples -----------+----------- test_stat | 10000 (1 row) test=# SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; relname | n_live_tup | n_dead_tup | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd -----------+------------+------------+-----------+-----------+-----------+--------------- test_stat | 10900 | 0 | 10900 | 0 | 0 | 0 (1 row) test=# DELETE FROM test_stat WHERE id > 10000; DELETE 900 test=# SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; relname | reltuples -----------+----------- test_stat | 10000 (1 row) test=# SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; relname | n_live_tup | n_dead_tup | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd -----------+------------+------------+-----------+-----------+-----------+--------------- test_stat | 10000 | 900 | 10900 | 0 | 900 | 0 (1 row) test=# UPDATE test_stat set some_number = 1 where id > 9100; UPDATE 900 test=# -- wait here (0.5 s) for statistics collector to catch up test=# SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; relname | reltuples -----------+----------- test_stat | 10000 (1 row) test=# SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; relname | n_live_tup | n_dead_tup | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd -----------+------------+------------+-----------+-----------+-----------+--------------- test_stat | 10000 | 1800 | 10900 | 900 | 900 | 10 (1 row) test=# ANALYZE test_stat; ANALYZE test=# test=# SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; relname | reltuples -----------+----------- test_stat | 10000 (1 row) test=# SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; relname | n_live_tup | n_dead_tup | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd -----------+------------+------------+-----------+-----------+-----------+--------------- test_stat | 10000 | 1800 | 10900 | 900 | 900 | 10 (1 row) test=# VACUUM test_stat; VACUUM test=# SELECT relname, reltuples FROM pg_class WHERE relname = 'test_stat'; relname | reltuples -----------+----------- test_stat | 10000 (1 row) test=# SELECT relname, n_live_tup, n_dead_tup, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd FROM pg_stat_user_tables WHERE relname = 'test_stat'; relname | n_live_tup | n_dead_tup | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd -----------+------------+------------+-----------+-----------+-----------+--------------- test_stat | 10000 | 0 | 10900 | 900 | 900 | 10 (1 row) test=# DROP TABLE test_stat; DROP TABLE Regards, Stefan |