PgSQL技术内幕 - 优化器如何估算行数

PgSQL技术内幕 - 优化器如何估算行数

PgSQL优化器根据统计信息估算执行计划路径的代价,从而选择出最优的执行计划。而这些统计信息来自pg_statistic,当然这个系统表是由ANALYZE或者VACUUM进行样本采集而来。关于该系统表的介绍详见:PgSQL技术内幕-Analyze做的那些事-pg_statistic系统表

在理解优化器估算行数原理前,先了解几个概念。

1、MCV

MCV即Most Common Values也就是表中出现频率最高的一批值,以KV形式存储在pg_statistic系统表中。将这些值从直方图中剔除可以减少极端值造成的估算误差。

2、等频直方图

直方图高度相同,每个桶宽度不同。如下图,每个桶Bucket里数值总个数相同,即为12。那么由于黑桶个数不同,导致有些Bucket跨度比较大。比如估算5的频率时,若在第一个Bucket频率占比为1/5,而第一个Bucket在整个直方图中占比为1/4,那么5的频率就是1/20。

314d67b2b212b3c19eba3620e4e7841b.png

3、打印执行计划时估算的行数

以select * from t1 where id2 =10;为例:

e483435aff7f9b0d7cac0ffda1942219.png

也就是执行计划节点Plan的plan_rows值。追本溯源,查看plan_rows值怎么计算得到的即可。从pg_class系统表获取对应表对应的行数rel->tuples,在query_planner调用到set_baserel_size_estimates函数时,将采样统计出表的行数rel->tuples * 选择率即得到估算行数。该估算行数在生成执行计划路径时放到路径path->rows中,进一步在创建SeqScan计划节点时由path->rows传递给Plan的rows,由此估算出了行数:

8174592de5d0585edfeb17ef9d1e640e.png

4、等值选择率

进一步,需要知道选择率如何计算。我们以=100为例:选择率函数包括join选择率评估函数都在selfuncs.c文件中,选择率调用函数堆栈:

clauselist_selectivity->clauselist_selectivity_simple->clause_selectivity->restriction_selectivity

restriction_selectivity中调用各个操作符对应的计算选择函数,等值过滤查询的选择率函数为eqsel:主要根据pg_statistic系统表的第一个卡槽的统计信息MCV:

eqsel_internal
  var_eq_const
  |--  if (HeapTupleIsValid(vardata->statsTuple)){
      //pg_statistic中的信息
      Form_pg_statistic stats;
      stats = (Form_pg_statistic) GETSTRUCT(vardata->statsTuple);
      nullfrac = stats->stanullfrac;//null值占比
    }
    if (vardata->isunique && vardata->rel && vardata->rel->tuples >= 1.0){
      //该列唯一约束
      selec = 1.0 / vardata->rel->tuples;
    }else if (HeapTupleIsValid(vardata->statsTuple) &&
       statistic_proc_security_check(vardata,(opfuncoid = get_opcode(operator)))){
      //有统计信息
      if (get_attstatsslot(&sslot, vardata->statsTuple,STATISTIC_KIND_MCV, InvalidOid,
               ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS)){
        //MCV卡槽取出最常见值统计信息sslot
        fmgr_info(opfuncoid, &eqproc);
        for (i = 0; i < sslot.nvalues; i++){//从最常见值数组中查找
          match = DatumGetBool(FunctionCall2Coll...,constval,sslot.values[i]));
          if (match)
            break;//落在MCV中break
        }
      }else{
        i = 0;
      }
      if (match){//落在MCV,选择率为MCV占比
        selec = sslot.numbers[i];
      }else{//没落在MCV中
        for (i = 0; i < sslot.nnumbers; i++)
          sumcommon += sslot.numbers[i];//mcv的总占比
        selec = 1.0 - sumcommon - nullfrac;//去掉mcv占比和null占比
        //(不同值个数 - 高频值个数)
        otherdistinct = get_variable_numdistinct(vardata, &isdefault) - sslot.nnumbers;
        if (otherdistinct > 1)
          selec /= otherdistinct;//(低频值总占比)/低频值总数=每个低频值的占比
      }
    }else{//没有analyze统计信息,猜一个选择率
      selec = 1.0 / get_variable_numdistinct(vardata, &isdefault);
    }

总结:

1)若100落在MCV中,则MCV的占比即为其选择率

2)若100没有落在MCV中,则选择率为:

(1- sumcommon - nullfrac)/(otherdistinct )即:低频值总占比/低频值总数

5、<=的选择率

等值过滤条件选择率计算没有用到直方图,<=的场景会用到等频直方图。<=的选择率计算函数为scalarlesel->scalarineqsel_wrapper->scalarineqsel:

scalarlesel->scalarineqsel_wrapper->scalarineqsel
  stats = (Form_pg_statistic) GETSTRUCT(vardata->statsTuple);
  //mcv中的选择率,计算同上
  mcv_selec = mcv_selectivity(vardata, &opproc, constval, true,&sumcommon);
  hist_selec = ineq_histogram_selectivity(root, ...);//直方图的选择率
  //合并mcv和直方图选择率
  selec = 1.0 - stats->stanullfrac - sumcommon;//非高频即直方图的占比
  selec *= hist_selec;//直方图中满足条件的选择率
  selec += mcv_selec;//加上mcv的选择率

重点关注直方图中如何计算ineq_histogram_selectivity,它使用二分查找法在直方图中进行查找,看100落在哪个桶上,如下图,比如100落在第2(标记序号为i)个桶上,那么满足条件的桶的个数n=(i-1)+(100-lowvalue)/(highvalue - lowvalue)。n/总桶数:(sslot.nvalues - 1)即为直方图中满足条件的行数占比。直方图的占比*非常见数的占比即为直方图中求得的满足条件的记录选择率。

e4c621289a92920ed6de0ad2012a7d35.png

当然,若有多个条件,则多个条件的选择率进行与或等(加/减)操作就可以得到多个条件下的选择率。

参考

https://www.postgresql.org/docs/current/planner-stats.html

https://postgrespro.com/blog/pgsql/5969296

https://postgrespro.com/list/thread-id/2676971

https://www.cnblogs.com/mlmz/p/15973106.html

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

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

相关文章

水泵房远程监控物联网系统

随着物联网技术的快速发展&#xff0c;越来越多的行业开始利用物联网技术实现设备的远程监控与管理。水泵房作为城市供水系统的重要组成部分&#xff0c;其运行状态的监控与管理至关重要。HiWoo Cloud作为专业的物联网云服务平台&#xff0c;为水泵房远程监控提供了高效、稳定、…

2.1HTML5基本结构

HTML5实际上不算是一种编程语言&#xff0c;而是一种标记语言。HTML5文件是由一系列成对出现的元素标签嵌套组合而成&#xff0c;这些标签以<元素名>的形式出现&#xff0c;用于标记文本内容的含义。浏览器通过元素标签解析文本内容并将结果显示在网页上&#xff0c;而元…

基于centos7的k8s最新版v1.29.2安装教程

k8s概述 Kubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态&#xff0c;其服务、支持和工具的使用范围相当广泛。 Kubernetes 这个名字源于希腊语&…

CentOS无法解析部分网站(域名)

我正在安装helm软件&#xff0c;参考官方文档&#xff0c;要求下载 get-helm-3 这个文件。 但是我执行该条命令后&#xff0c;报错 连接被拒绝&#xff1a; curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 # curl: (7) Fai…

深入探索Java中的MarkWord与锁优化机制——无锁、偏向锁、自旋锁、重量级锁

引言 在Java并发编程领域&#xff0c;有效管理对共享资源的访问显得尤为关键。为了保障线程安全&#xff0c;Java虚拟机&#xff08;JVM&#xff09;引入了一系列精妙的锁机制&#xff0c;这其中的核心概念就是Java对象头中的MarkWord。本文将详尽解析MarkWord的作用&#xff…

基于Centos7部署OceanBase4.2版本单副本集群

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

1.绪论

目录 1.1 Web原理基础 1.1.1 Internet与万维网 1.1.2 Web架构 1.2 Web前端技术基础 1.2.1 HTML技术 1.2.2 CSS技术 1.2.3 JavaScript技术 1.3 Web前端新技术 1.3.1 HTML5技术 1.3.2 CSS3技术 1.3.3 jQuery技术 1.4 Web开发工具 1.1 Web原理基础 1.1.1 Internet与万…

Java实现PDF文字内容识别,结合OCR实现PDF图片实现

使用插件&#xff1a;UMI-OCR、PDFBOX 实现思路&#xff1a;通过PDFBOX识别PDF文字&#xff0c;如果是图片&#xff0c;则识别不出来&#xff0c;再调用OCR进行识别返回文字&#xff1b;OCR识别较慢&#xff0c;长图识别不出来&#xff0c;目前HTTP方式只支持图片格式&#xf…

2024年【流动式起重机司机】考试题及流动式起重机司机模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 流动式起重机司机考试题参考答案及流动式起重机司机考试试题解析是安全生产模拟考试一点通题库老师及流动式起重机司机操作证已考过的学员汇总&#xff0c;相对有效帮助流动式起重机司机模拟考试题学员顺利通过考试。…

008:安装Docker

安装Docker 如果不太熟悉Linux命令&#xff0c;不想学习Linux命令&#xff0c;可以直接看文末NAS面板章节&#xff0c;通过面板&#xff0c;像使用Window一样操作NAS。 一、安装 Docker 1.安装 Docker wget -qO- https://get.docker.com/ | sh2.启动 Docker 服务 sudo sys…

Ubuntu系统的安装及基础操作

目录 一、VMware虚拟机安装Ubuntu20.04过程 1、安装前的准备工作 2、VMware虚拟机创建Ubuntu操作系统 步骤一&#xff1a;以管理员的身份运行VMware虚拟机 步骤二&#xff1a;新建虚拟机 步骤三&#xff1a;选择类型配置 步骤四&#xff1a;选择安装客户机操作系统 步骤…

100W-150W电阻器-TO-247模压厚膜电阻(1)

EAK封装的TO-247功率电阻器为设计工程师提供稳定的晶体管式封装的大功率电阻器件&#xff0c;功率为100W-150W。这些电阻器专为需要精度和稳定性的应用而设计。该电阻器采用氧化铝陶瓷层设计&#xff0c;可将电阻元件和安装片分开。 EAK模压TO-247厚膜功率电阻器 这种结构提供了…

蓝桥杯刷题|02入门真题

[蓝桥杯 2022 省 B] 刷题统计 题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a 道题目&#xff0c;周六和周日每天做 b 道题目。请你帮小明计算&#xff0c;按照计划他将在第几天实现做题数大于等于 n 题? 输入格式 输入一行包含三个整数…

react04- mvc 、 mvvm

MVC与MVVM stackoverflow论坛网站 react前端框架 使用框架前&#xff1a; 操作dom > js获取dom元素&#xff0c;事件侦听&#xff0c;修改数据&#xff0c;设置样式。。。 操作dom问题: 直接操作dom&#xff0c;会造成大量的回流、重绘&#xff0c;消耗大量性能操作起来也…

物联网终端telegraf采集设备信息

背景 低功耗设备上资源有限&#xff0c;但又比较重要。对其的管理难度很大&#xff0c;有些时候又必须时刻了解其运行状况。我们自然想到的是能否有办法监控它呢&#xff1f;当时是有的&#xff01;而且很成熟的解决方案。TICK技术栈&#xff0c;那TICK是什么呢&#xff1f; TI…

云仓酒庄2024年培训专业化:强化销售与品酒技能,酒业新动态

云仓酒庄2024年培训专业化&#xff1a;强化销售与品酒技能&#xff0c;共筑酒业新动态 在风云变幻的市场竞争中&#xff0c;云仓酒庄始终秉持着创新、进取的理念&#xff0c;不断探索与实践&#xff0c;以推动酒业行业的持续健康发展。2024年&#xff0c;云仓酒庄在培训专业化…

SpringBoot(自定义转换器+处理Json+内容协商)

文章目录 1.自定义转换器1.代码实例1.save.html2.编写两个bean1.Car.java2.Monster.java 3.WebConfig.java 配置类来自定义转换器4.测试 2.注意事项和细节1.debug查看转换器总数1.打断点2.执行到断点后&#xff0c;选左边的1923.可以看出&#xff0c;加上自定义的转换器一共125…

Day63:WEB攻防-JS应用算法逆向三重断点调试调用堆栈BP插件发包安全结合

目录 前置知识 JS调试分析 JS分析调试结合Burp JS分析调试知识点&#xff1a; 1、JavaScript-作用域&调用堆栈 2、JavaScript-断点调试&全局搜索 3、JavaScript-Burp算法模块使用 前置知识 JS加密数据走向 浏览器调试 1、作用域&#xff1a;&#xff08;本地&全…

论文阅读——RingMo

RingMo: A Remote Sensing Foundation Model With Masked Image Modeling 与自然场景相比&#xff0c;RS图像存在以下困难。 1&#xff09;分辨率和方位范围大&#xff1a;受遥感传感器的影响&#xff0c;图像具有多种空间分辨率。此外&#xff0c;与自然图像的实例通常由于重…

《1w实盘and大盘基金预测 day3》

上贴指数预测拉满&#xff0c;上证最低位置和最高位置预测的八九不离十&#xff0c;个人预测最高3062实际3060&#xff0c;最低3017实际3020 昨天的预测 3017-3031-3062 低开反抽&#xff0c;回落下杀 明天看是否能阳包阴&#xff0c;得看蓝筹、证券发力。&#xff08;AI板块…