PostgreSQL技术内幕23:PG统计信息的收集和应用

0.简介

数据库统计信息是数据库管理系统(DBMS)中用于优化查询性能和提高数据库效率的重要元数据,其中包含很多关键信息,能够为优化器生成合理的查询计划提供数据支撑,本文将对PG统计信息收集方式,关键的统计信息以及其优化器使用原理方面进行介绍。

1.统计信息收集方式

1.1 统计信息收集的形式(独立进程 or 进程内部处理)

PG统计信息收集在PG15之前使用stats collector(统计信息收集器,一个独立的进程)来进行统计信息收集,收集统计信息需要跟踪每个进程的活动,比如扫描表和索引的次数,或者最后一次vacuum以及自动vacuum在表上的运行时间、运行次数。这些信息都是通过UDP的包传递给该收集进程,这种方法存在很多问题:1)过时的统计信息 2)进程未运行 3)其通过写入临时文件的方式来共享,会带来大量I/O操作。

PG15将其独立进程去掉,做了以下优化:1)不在使用临时文件而是使用共享内存来进行通信统计数据(在startup阶段读取,在shutdown阶段持久化),减少I/O操作。2)不在依赖运行的统计进程,减少统计信息丢失,提高可靠性。3)简化其他进程工作,如vacuum。

因为本文基于PG 11来进行的分析,所以还有独立进程概念,其原理一致,只是形式上的差异。

1.2 统计信息收集的使用方式

PG统计信息收集支持两种操作,一种是手动执行,一种是自动执行

1)手动执行:analyze/vacuum analyze

  1. 自动执行:自动执行包含两种,一是在事务提交/回滚时发消息给进程更新信息,另外autovacuum launcher会定期读取文件,当某个表改动超过阈值时便会触发一次提交信息更新操作。

2.关键统计信息介绍

在PG中,统计信息可以分成两部分,一是数据分布的统计信息,描述数据的分布状况,其存储与pg_statistic系统表中,其不容易阅读,可以查看pg_stats视图来了解其内部信息;另外一类是运行状态的统计数据。其中pg_stats可以使用如下命令查看,具体字段含义见下方表格

cpp 复制代码
\d+ pg_stats

3. 统计信息收集原理

如何收集统计信息,也就是如何去对信息进行抽样统计,PG抽样算法如下:

1)选择采样函数:内部数据采用acquire_sample_rows,外部表使用外部表插件的实现。

2)获取表的每个字段信息并将结果返回。

3)针对每个字段来进行处理。

需要说明的是在采样过一次在采样过程中并不会处理事务中的记录(如正在插入和删除的记录),但是如果其是在analyze所在的事务中执行的,就会加入统计,这点可能造成统计顺序不准确(如两次analyze并发执行,结果可能不一致且覆盖,或者长事务结束前后统计信息相差较大)。

另外对于采样的大小,PG的使用的公式来自于论文:《Random sampling for histogram construction: how much is enough?》,PG实现可以看std_typanalyze函数。

cpp 复制代码
 在表大小为n,矩形图大小为k,分组内相关最大相关性错误为f,错误可能为gamma的情况下,最小的样本大小如下:
    r = 4 * k * ln(2*n/gamma) / f^2
    取f=0.5,gamma=0.01,n=10^6,我们可以得到
    r = 305.82 * k
    可以看到,元组数对样本大小的影响很小,即使元组数为10^12,采样出错的概率也不高,因此PG统一使用300作为采样的权值,简化问题,在确定样本大小时无需获取表大小。

使用的随机数算法是Knuth's Algorithm S。

cpp 复制代码
设k为样本大小, K为抽样对象大小, i为当前对象,V生成的0-1之间的随机数 
while i < k
    p = k/(K - i); 
    if V < p
      pick it
      k--;
    i++

4.优化器使用原理

统计信息在优化器的作用通过一个查询来说明,如果发现满足where的条件很少的话就会倾向于走索引扫描,反之走顺序扫描(减少二次回表)。

相关推荐
ClouGence10 小时前
SQL Server CDC 能放到 Always On 备库读吗?一文讲透原理与实践
数据库·sql server
先吃饱再说1 天前
存储的进化:从 MySQL 到浏览器缓存,数据到底住在哪?
数据库
Nturmoils1 天前
字段太多看不全,ksql 的展开模式和输出控制怎么用
数据库·后端
Databend1 天前
Agent 轨迹分析与归因的数据工程实践
大数据·数据库·agent
这个DBA有点耶1 天前
SQL改写进阶:标量子查询的“隐形代价”与消除实战
数据库·mysql·架构
smallyoung1 天前
数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南
数据库·mysql·postgresql
parade岁月1 天前
MySQL JOIN解析:朴实无华但食之有味
数据库·后端
用户3169353811831 天前
MySQL服务无法启动问题解决全记录
数据库
vivo互联网技术1 天前
从 10 分钟到 1 秒:ES 深度分页任意跳页的三轮优化实战
服务器·数据库·redis·elasticsearch·深度分页
倔强的石头_2 天前
《Kingbase护城河》——猎捕慢查询:执行计划的微观解析与索引调优实战
数据库