vb:统计信息专题

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;

例:

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容