1.概览

2.运行信息

2.1 pg_stat*运行信息

pg_stat_all_tables
pg_stat_all_tables常用于查看表行数变更情况:
- n_tup*: 表DML\ctas(会写入n_tup_ins)变更的行数,持续累加,事务提交/回滚时更新。
- n_live_tup: insert\ctas\truncate\analyze触发更新, analyze将获取表中实际情况进行更新。
- n_dead_tup: deletelupdate\truncate(只将活行和死行数归零,不会更新增删改查行数)\vacuum\analyze, analyze将获取表中实际情况进行更新,vacuum在原先基础上减去。
- last_data_changed: 表上一次数据变更的时间。需设置enable_save_datachanged_timestamp=on,否则不会记录。

触发autovacuum需满足的条件:
pg_stat_all_tables.n_dead_tuples >= autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor * pg_class.reltuples
触发autoanalyze需满足的条件:
pg_stat_get_tuples_changed(pg_class.oid) >= autovacuum_analyze_threshold + autovacuum_analyze_scale_factor * pg_class.reltuples
注意:pg_class也是需要analyze的。所以一般我们手动导入一个库后,要手动analyze一下,因为某些表如果没达到自动触发的条件,就不会触发了,小表就没有统计。
附:査询应触发autoanalyze、autovacuum的对象:
with tmp as (
select a.relid, a.relname,
pg_stat_get_tuples_changed(a.relid) as n_changed,
(current_setting('autovacuum_analyze_threshold') + current_setting('autovacuum_analyze_scale_factor')* b.reltuples) as n_autoanalyze,
a.n_dead_tup,
(current_setting('autovacuum_vacuum_threshold') + current_setting('autovacuum_vacuum_scale_factor')* b.reltuples) as n_autovacuum, last_autovacuum, last_vacuum, last_autoanalyze, last_analyze from pg_stat_all_tables a, pg_class b
where a.relid=b.oid)
select * from tmp where n_changed>=n_autoanalyze
union
select * from tmp where n_dead_tup>=n_autovacuum;
(原因:达到阈值但还没自动触发;或入不敷出,清理速度赶不上产生速度,死元组堆积)
2.2 pg_stat*数据存储与更新
【存储】
- 数据库启动时,存储在内存,并刷新到临时目录。
stat _tmp_directory=pg_stat_tmp,即$PGDATA/pg_stat_tmp - 数据库关闭时,落盘到global/pgstat.stat(PG是$PGDATA/pg_stat/pgstat.stat)
【更新】
- 由事务提交/回滚、vacuum、truncate、tempfile等行为提交数据至statscollector
- 由statscollector每500ms落盘

【重置】
- 数据库非正常停库,起库时需要Recovery,则清除pgstat: [Pgstat] remove statfiles in pg_stat tmp/pgstat.stat, global/pgstat.stat
- 手工执行pg_stat_reset()
3.分析数据

pg_class
pg_class 系统目录表中,存储了表级统计信息:
- 元组数量(reltuples)
- 页面数量(relpages)
- 可见性映射中标记的页面数量(relallvisible)

- cost = relpages * seg_page_cost + retuples * cpu_tuple_cost = 17656 * 1+ 988697 * 0.01 = 27542.97
- rows = reltuples = 988697
如果表还未analyze, 或为空表, pg_class中reltuples、relpages为0, 生成执行计划时:
- 默认该表relpages = 10
- 根据行长估算rows: 页面8192字节,页头36字节,行指针4字节,行头24字节,行宽width,即10*8156/(28+width),是个比较粗略的算法

pg_stats
- 依赖Analyze 采样分析, 300*default_statistics_target

注:这个参数用于会话中。
- 空值比例 null frac
- estimated_rows = reltuples x selectivity

- 高频值(MCV、MCF):most_common_vals、most_common_fregs

注:高频值最多存100个。
- 非重复值 n_distinct: >0时为非重复值的估计数目, <0时绝对值为非重复值占总行数的比例
- estimated rows = reltuples * (1 - null_frac - sum(mcf))/(N(非重复值个数) - count(mcv))

- 直方图: 非重复值数量>100(mcv上限),则会记入直方图,值会分布在直方图的多个桶之间。空值和mcv不记入直方图。
- estimated_rows = reltuples * ((1-null_frac-sum(mcf))/N(桶数) ) * M(命中桶数)


例:

pg_statistic_ext多列统计信息
create table t1(a int, b int);
insert into t1 select mod(i,100),mod(i,100) from
generate_series(1,1000000) i;
vacuum analyze t1;
explain analyze select * from t1 where a= 1 and b = 1;
创建多列统计信息:
alter table t1 add statistics((a,b));
set default_statistics_target=-5,
analyze t1((a,b));
注:创建多列统计信息要求default_statistics_target要设为<0的值。
再次查看估算值:
explain analyze select * from t1 where a= 1 and b = 1;
使用不存在的数值对:
explain analyze select * from t1 where a = 1 and b = 2;
例:
