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的条件很少的话就会倾向于走索引扫描,反之走顺序扫描(减少二次回表)。

相关推荐
步步为营DotNet6 分钟前
5-2EFCore性能优化
数据库·性能优化·.net
2501_920047031 小时前
Redis-集群
数据库·redis·bootstrap
半夏陌离1 小时前
SQL 拓展指南:不同数据库差异对比(MySQL/Oracle/SQL Server 基础区别)
大数据·数据库·sql·mysql·oracle·数据库架构
旋转的油纸伞2 小时前
SQL表一共有几种写入方式
数据库·sql
半夏陌离2 小时前
SQL 入门指南:排序与分页查询(ORDER BY 多字段排序、LIMIT 分页实战)
java·前端·数据库
isyoungboy2 小时前
SQL高效处理海量GPS轨迹数据:人员gps轨迹数据抽稀实战指南
数据库·sql
敬业小码哥2 小时前
记一次:mysql的json及json数组使用组合使用
数据库·mysql·json
练小杰3 小时前
【Mysql-installer-community-8.0.26.0】Mysql 社区版(8.0.26.0) 在Window 系统的默认安装配置
数据库·sql·mysql·adb·配置文件·mysql安装·关系型数据库
陈陈爱java4 小时前
Spring八股文
开发语言·javascript·数据库
拾忆,想起4 小时前
Redis复制延迟全解析:从毫秒到秒级的优化实战指南
java·开发语言·数据库·redis·后端·缓存·性能优化