PgSQL技术内幕-Analyze做的那些事-pg_statistic系统表

PgSQL的优化器为一个查询生成一个执行效率相对较高的物理执行计划树。执行效率的高低依赖于代价估算。比如估算查询返回的记录条数、记录宽度等,就可以计算出IO开销;也可以根据要执行的物理操作估算出CPU代价。那么估算依赖的信息来源哪呢?系统表pg_statistic(列级别统计信息为代价估算提供了关键统计信息。Analyze操作或者vacuum进行了统计信息采集,并将对数据按列进行分析,得到每列的数据分布、最常见值、频率等信息,更新到pg_statistic表。当然还有表级别的统计信息,存储在系统表pg_class:relptuples表示表的总元组数,relpages表示总页面数,等。

Analyze具体都做哪些事呢?本文先介绍下pg_statistic系统表。

1、pg_statistic

首先需要了解analyze都输出哪些信息到系统表。也就是pg_statistic系统表每列的含义。

postgres=# \d+ pg_statistic
                         数据表 "pg_catalog.pg_statistic"
    栏位     |   类型   | 校对规则 |  可空的  | 预设 |   存储   | 统计目标 | 描述
-------------+----------+----------+----------+------+----------+----------+------
 starelid    | oid      |          | not null |      | plain    |          |
 staattnum   | smallint |          | not null |      | plain    |          |
 stainherit  | boolean  |          | not null |      | plain    |          |
 stanullfrac | real     |          | not null |      | plain    |          |
 stawidth    | integer  |          | not null |      | plain    |          |
 stadistinct | real     |          | not null |      | plain    |          |
 stakind1    | smallint |          | not null |      | plain    |          |
 stakind2    | smallint |          | not null |      | plain    |          |
 stakind3    | smallint |          | not null |      | plain    |          |
 stakind4    | smallint |          | not null |      | plain    |          |
 stakind5    | smallint |          | not null |      | plain    |          |
 staop1      | oid      |          | not null |      | plain    |          |
 staop2      | oid      |          | not null |      | plain    |          |
 staop3      | oid      |          | not null |      | plain    |          |
 staop4      | oid      |          | not null |      | plain    |          |
 staop5      | oid      |          | not null |      | plain    |          |
 stacoll1    | oid      |          | not null |      | plain    |          |
 stacoll2    | oid      |          | not null |      | plain    |          |
 stacoll3    | oid      |          | not null |      | plain    |          |
 stacoll4    | oid      |          | not null |      | plain    |          |
 stacoll5    | oid      |          | not null |      | plain    |          |
 stanumbers1 | real[]   |          |          |      | extended |          |
 stanumbers2 | real[]   |          |          |      | extended |          |
 stanumbers3 | real[]   |          |          |      | extended |          |
 stanumbers4 | real[]   |          |          |      | extended |          |
 stanumbers5 | real[]   |          |          |      | extended |          |
 stavalues1  | anyarray |          |          |      | extended |          |
 stavalues2  | anyarray |          |          |      | extended |          |
 stavalues3  | anyarray |          |          |      | extended |          |
 stavalues4  | anyarray |          |          |      | extended |          |
 stavalues5  | anyarray |          |          |      | extended |          |
索引:
    "pg_statistic_relid_att_inh_index" UNIQUE, btree (starelid, staattnum, stainherit)
访问方法 heap

Catalog定义在pg_statistic.h中:

/* ----------------
 *    pg_statistic definition.  cpp turns this into
 *    typedef struct FormData_pg_statistic
 * ----------------
 */
CATALOG(pg_statistic,2619,StatisticRelationId)
{
  /* These fields form the unique key for the entry: */
  Oid      starelid;    /* relation containing attribute */
  int16    staattnum;    /* attribute (column) stats are for */
  bool    stainherit;    /* true if inheritance children are included */


  /* the fraction of the column's entries that are NULL: */
  float4    stanullfrac;


  /*
   * stawidth is the average width in bytes of non-null entries.  For
   * fixed-width datatypes this is of course the same as the typlen, but for
   * var-width types it is more useful.  Note that this is the average width
   * of the data as actually stored, post-TOASTing (eg, for a
   * moved-out-of-line value, only the size of the pointer object is
   * counted).  This is the appropriate definition for the primary use of
   * the statistic, which is to estimate sizes of in-memory hash tables of
   * tuples.
   */
  int32    stawidth;


  /* ----------------
   * stadistinct indicates the (approximate) number of distinct non-null
   * data values in the column.  The interpretation is:
   *    0    unknown or not computed
   *    > 0    actual number of distinct values
   *    < 0    negative of multiplier for number of rows
   * The special negative case allows us to cope with columns that are
   * unique (stadistinct = -1) or nearly so (for example, a column in which
   * non-null values appear about twice on the average could be represented
   * by stadistinct = -0.5 if there are no nulls, or -0.4 if 20% of the
   * column is nulls).  Because the number-of-rows statistic in pg_class may
   * be updated more frequently than pg_statistic is, it's important to be
   * able to describe such situations as a multiple of the number of rows,
   * rather than a fixed number of distinct values.  But in other cases a
   * fixed number is correct (eg, a boolean column).
   * ----------------
   */
  float4    stadistinct;


  /* ----------------
   * To allow keeping statistics on different kinds of datatypes,
   * we do not hard-wire any particular meaning for the remaining
   * statistical fields.  Instead, we provide several "slots" in which
   * statistical data can be placed.  Each slot includes:
   *    kind      integer code identifying kind of data (see below)
   *    op        OID of associated operator, if needed
   *    coll      OID of relevant collation, or 0 if none
   *    numbers      float4 array (for statistical values)
   *    values      anyarray (for representations of data values)
   * The ID, operator, and collation fields are never NULL; they are zeroes
   * in an unused slot.  The numbers and values fields are NULL in an
   * unused slot, and might also be NULL in a used slot if the slot kind
   * has no need for one or the other.
   * ----------------
   */


  int16    stakind1;
  int16    stakind2;
  int16    stakind3;
  int16    stakind4;
  int16    stakind5;


  Oid      staop1;
  Oid      staop2;
  Oid      staop3;
  Oid      staop4;
  Oid      staop5;


  Oid      stacoll1;
  Oid      stacoll2;
  Oid      stacoll3;
  Oid      stacoll4;
  Oid      stacoll5;


#ifdef CATALOG_VARLEN      /* variable-length fields start here */
  float4    stanumbers1[1];
  float4    stanumbers2[1];
  float4    stanumbers3[1];
  float4    stanumbers4[1];
  float4    stanumbers5[1];


  /*
   * Values in these arrays are values of the column's data type, or of some
   * related type such as an array element type.  We presently have to cheat
   * quite a bit to allow polymorphic arrays of this kind, but perhaps
   * someday it'll be a less bogus facility.
   */
  anyarray  stavalues1;
  anyarray  stavalues2;
  anyarray  stavalues3;
  anyarray  stavalues4;
  anyarray  stavalues5;
#endif
} FormData_pg_statistic;

列描述

1)starelid表示当前列所属的表或者索引

2)staattnum表示本行统计细腻些属于上面表或者索引的第几列

3)stainherit表示统计信息是否包含子列。通常情况下,analyze后每个表列都会有一个条目,并且stainerit为false。如果该表有分区子表,那么还会创建stainherit=true的第2条记录。其实stainherit=true,可以认为是父表,也就是这一行是所有子表的列的统计信息,而stainherit=false,则认为是叶子表,仅表示该子表的列的统计信息。

4)stanullfrac表示该列中NULL个数的比例

5)stawidth表示该列非空值的平均宽度

6)stadistinct表示列中非空值唯一值个数,即去重后的个数或比例。>0表示唯一值个数。=0表示唯一值个数未知。<0表示其绝对值去重后个数占总个数的比例,比如80%的个数是非NULL,平均每个非NULL值出现2次,那么这个是就可以表示为-0.4

7)stakindN用来表示统计信息的形式,即后面number、values所表示的数据的用途,用于生成pg_stats.统计信息形式的定义如下:

#define STATISTIC_KIND_MCV  1
#define STATISTIC_KIND_HISTOGRAM 2
#define STATISTIC_KIND_CORRELATION  3
#define STATISTIC_KIND_MCELEM 4
#define STATISTIC_KIND_DECHIST  5
#define STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM 6
#define STATISTIC_KIND_BOUNDS_HISTOGRAM 7

PG数据库对每个属性列的统计目前最多只能应用5(STATISTIC_NUM_SLOTS)种统计方法,因此在pg_statistic中会有stakind1--stakind5、staop1--staop5、stanumbers1--stanumbers5以及stavalues1--stavalues5共5个slot。如果stakind不为0,则表示该对应slot有统计信息。第一个统计方法的信息会先记录到第一个slot中(stakind1、staop1、statnumber1、stavalues1),第2个统计方法信息会记录到第二个slot中(stakind2、staop2、statnumber2、stavalues2),依次类推,可有存5个统计方法信息。而stakindi的值则为上述统计信息形式的宏定义。比如1表示MCV值;2表示直方图的值;3表示相关性的值等。Kind的范围:1-99:内核占用;100-199,PostGIS占用;200-299,ESRI ST_Geometry几何系统占用;300-9999,未来公共占用。

8)staopN用来表示该统计值支持的操作,如“=”或者“<”

9)stacollN用来表示统计信息的排序规则

10)stanumbersN用来表示如果是MCV类型,这里就是下面对应stavaluesN出现的概率值

11)stavaluesN用来表示统计值数组

例:表t4有两列,分别插入两次1--1000的值:

create table t4(id1 int,id2 int);
insert into t4 select generate_series(1,1000),generate_series(1,1000);
insert into t4 select * from t4;

说明:

  • id1列应用了3个统计方法,占了3个slot,分别是MCV(1)、直方图(2)、相关系数(3)

  • stakind1为1,表示使用MCV,stanumbers1保存的是高频值数组,数组中记录的是每个高频值占用的频率值,而stavalues1则保存的是高频数数组对应的数值。

  • stakind3为3,表示使用相关性,stanumbers3中保存的是相关系数。若相关系数为1,则表示数据分布和排序(按物理位置)后的数据分布完全正相关。

  • stakind2为2,表示使用直方图,stavalues2保存的是直方图每个slot的边界值。因为用的是等频直方图,只需要记录每个桶边界值,就可以获取的每个桶的平均比例。

36159fcb756b0191a5c48eb1de7a1d50.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/135961.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代理模式-静态动态代理-jdk动态代理-cglib动态代理

代理模式 静态代理 动态代理&#xff1a;jdk动态代理 cglib动态代理 注意 &#xff1a;下面的代码截图 要配合文字去看 我对代码的每一步都做了解释 所以需要配合图片观看提取吗1111https://pan.baidu.com/s/1OxQSwbQ--t5Zvmwzjh1T0A?pwd1111 这里直接把项目文件 及代码 …

【Seata源码学习 】 AT模式 第一阶段 @GlobalTransaction的扫描

1. SeataAutoConfiguration 自动配置类的加载 基于SpringBoot的starter机制&#xff0c;在应用上下文启动时&#xff0c;会加载SeataAutoConfiguration自动配置类 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfigurationio.seata.spring.boot.aut…

外中断的应用

前言 软件基础操作参考这篇博客&#xff1a; LED数码管的静态显示与动态显示&#xff08;KeilProteus&#xff09;-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/134101256?spm1001.2014.3001.5501实验一&#xff1a;P1口上接8个LED灯&#xff0c;在外部…

cesium如何实现区域下钻

首先&#xff0c;这里讲一下数据源&#xff0c;数据源是拷贝的DataV.GroAtlas里的数据&#xff0c;这里整合了一下之前发的区域高亮的代码来实现的&#xff0c;单击左键使得区域高亮&#xff0c;每次点击都移除上一次点击的模块&#xff0c;双击左键&#xff0c;实现区域下钻并…

C++ 对象的拷贝、赋值、清理和移动(MyString类)

MyString类 MyString.h #ifndef MYSTRING_H #define MYSTRING_H#include <iostream> using namespace std;class MyString {private:char* str nullptr;unsigned int MaxSize 0;public:MyString(); /*默认构造函数*/MyString(unsigned int n); /*有…

SpringBoot系列-2 自动装配

背景&#xff1a; Spring提供了IOC机制&#xff0c;基于此我们可以通过XML或者注解配置&#xff0c;将三方件注册到IOC中。问题是每个三方件都需要经过手动导入依赖、配置属性、注册IOC&#xff0c;比较繁琐。 基于"约定优于配置"原则的自动装配机制为该问题提供了一…

recycleView(二)Grid,中间有间距,left,right,top,bottom没有间距

1.作用 1.效果图 item的top&#xff0c;bottom&#xff0c;right&#xff0c;left都是0 2.代码 1.关键代码 // 设置RecycleView的item间的间距&#xff0c;上下间距为20排序&#xff0c;左右间距为20排序binding.rv.addItemDecoration(object : RecyclerView.ItemDecorat…

算法——滑动窗口

什么是窗口&#xff1f;就是符合题目要求的区域内的数据&#xff0c;将每次符合数据的窗口内的数据记录下来&#xff0c;然后将窗口后移&#xff0c;寻找其他符合要求的数据&#xff0c;每次进入窗口和退出窗口都需要一定的要求 一、 LCR 008. 长度最小的子数组 - 力扣&#…

数据结构—二叉树的模拟实现(c语言)

目录 一.前言 二.模拟实现链式结构的二叉树 2.1二叉树的底层结构 2.2通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树 2.3二叉树的销毁 2.4二叉树查找值为x的节点 2.5二叉树节点个数 2.6二叉树叶子节点个数 2.7二叉树第k层节点个数 三.二叉树的遍历 3.1…

Keras实现图注意力模型GAT

简介&#xff1a;本文实现了一个GAT图注意力机制的网络层&#xff0c;可以在Keras中像调用Dense网络层、Input网络层一样直接搭积木进行网络组合。 一&#xff0c;基本展示 如下图所示&#xff0c;我们输入邻接矩阵和节点特征矩阵之后&#xff0c;可以直接调用myGraphAttention…

C语言之pthread_once实例总结(八十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

史上最全最新Ubuntu20.04安装教程(图文)

总的来说&#xff0c;安装Ubantu包含以下三个步骤&#xff1a; 一、安装虚拟机 二、Ubuntu镜像下载 三、虚拟机配置 一、安装虚拟机 选择安装VMware Workstation&#xff0c;登录其官网下载安装包&#xff0c;链接如下&#xff1a; 下载 VMware Workstation Pro​www.vmwa…

设计模式之--原型模式(深浅拷贝)

原型模式 缘起 某天&#xff0c;小明的Leader找到小明:“小明啊&#xff0c;如果有个发简历的需求&#xff0c;就是有个简历的模板&#xff0c;然后打印很多份&#xff0c;要去一份一份展示出来&#xff0c;用编程怎么实现呢&#xff1f;” 小明一听&#xff0c;脑袋里就有了…

ARM64 linux并发与同步之内存屏障

1.2 内存屏障 1.2.1 概念理解 原理部分比较苦涩难懂&#xff0c;我们先不过多详细介绍这部分的由来和经过&#xff0c;接下来着重讲解什么用途和实现&#xff1b; ARM64架构中提供了3条内存屏障指令。 数据存储屏障(Data Memory Barrier, DMB)指令。数据同步屏障(Data Synch…

劲松HPV防治诊疗中心发布:HPV感染全面防治解决方案

在当今社会&#xff0c;HPV(人乳头瘤病毒)感染问题已成为广大公众关注的焦点。作为一种高度传染性的病毒&#xff0c;HPV感染不仅可能导致生殖器疣&#xff0c;还可能引发各种癌症。面对这一严重威胁&#xff0c;劲松HPV防治诊疗中心以其专业的医疗团队、正规的治疗流程和全方位…

Python基础入门例程51-NP51 列表的最大与最小(循环语句)

最近的博文&#xff1a; Python基础入门例程50-NP50 程序员节&#xff08;循环语句&#xff09;-CSDN博客 Python基础入门例程49-NP49 字符列表的长度-CSDN博客 Python基础入门例程48-NP48 验证登录名与密码&#xff08;条件语句&#xff09;-CSDN博客 目录 最近的博文&…

函数极限求解方法归纳

1、连续函数直接代入值&#xff08;加减不可以部分代入值&#xff09; 例题1 配凑构造等价无穷小 等价无穷小 注意&#xff1a;不要在加减中部分使用等价无穷小&#xff0c;可以利用拆极限的方式求&#xff0c;拆出来的每一部分都要有极限&#xff0c;如果有一部分没有极限就是…

STM32F4X定时器之通用定时器

一、STM32通用定时器概述 通用定时器包括一个16位或32位自动重载计数器&#xff0c;可通过可编程预分频器进行驱动。定时器可以实现多种功能&#xff0c;包括测量输入信号的脉冲宽度和生成输出波形&#xff0c;通过使用定时器预分频器和RCC时钟控制器预分频器&#xff0c;可以…

目标检测——Yolo系列(YOLOv1/2/v3/4/5/x/6/7/8)

目标检测概述 什么是目标检测&#xff1f; 滑动窗口&#xff08;Sliding Window&#xff09; 滑动窗口的效率问题和改进 滑动窗口的效率问题&#xff1a;计算成本很大 改进思路 1&#xff1a;使用启发式算法替换暴力遍历 例如 R-CNN&#xff0c;Fast R-CNN 中使用 Selectiv…

C++算法:完美矩形

题目 给你一个数组 rectangles &#xff0c;其中 rectangles[i] [xi, yi, ai, bi] 表示一个坐标轴平行的矩形。这个矩形的左下顶点是 (xi, yi) &#xff0c;右上顶点是 (ai, bi) 。 如果所有矩形一起精确覆盖了某个矩形区域&#xff0c;则返回 true &#xff1b;否则&#xf…