PostgreSQL Explain 复杂执行计划怎么看 --- 逐个分解PG执行计划的那些操作

news2024/11/23 14:59:06

1c071022c70730b10de2f2bed77d1758.png

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共700人左右 1 + 2)。

每个数据中都希望自己的SQL 的执行计划是最好的,最快的,最妙的,但是在你使用EXPLAIN 的命令的情况下,你看的懂里面的那些东西吗?如果你看不懂,你怎么知道你的执行计划是最好的,最棒的,最妙的。

1  数据扫描获取方式

  • Sequential Scan

  • Index Scan

  • Index Only Scan

  • Bitmap Scan

  • TID Scan

在PG的数据库获取数据的方式中,有以上的一些方式来获取数据的方式的名字展示。

Sequential Scan

1  顺序扫描,顺序扫描是一种数据获取的方式,举例如果您想获取 1000万行数据中的一条数据,使用这样的方式,即使你的数据可能就在1000万上数据的第一条,那么他还是会将1000万数据全部进行扫描,并匹配后,在给出结果。数据在数据库库存储是通过页面来存储的,假设1000个页面存储了1000万行的数据每个页面,那么扫描的方式就是 1000 (页)* 10000(行)的方式进行数据的扫描。

顺序扫描的方式的使用可能会符合以下的几个条件

1   没有合适的索引使用

2   获取的数据占比整体表是占大多数的

2  INDEX SCAN 

INDEX SCAN 虽然也有SCAN ,扫描,但是这个扫描的COST 相对于上面的扫描,不是一个意义,INDEX SCAN 并不是顺序扫描的方式,而是按照索引查找定位数据的方式,通过非常低廉的索引SEARCH 的方式,并通过索引存储的指针指向具体的数据部分,获取数据。

考量是否用索引来解决问题

1  有合适的对应的索引

2   数据提取的量占据整体的数据量是少数,或极少数

3   随机数据获取相对于顺序范围数据获取,更容易使用索引获取数据

4    在成本估算后,索引扫描优于顺序扫描

在以上的情况下,索引扫描才可以启用

3  INDEX Only Scan 

INDEX only Scan 与上面的index scan 在原理上是一致的,但是在操作的步骤上是不一样的,INDEX only Scan 在获取数据时,并不会在返回到原表中获取数据,而是我们的数据已经在索引中了,所以直接在索引获取数据后就返回了,节省了相关的第二次操作的消耗。

满足使用INDEX ONLY SCAN 方式,需要

1  有合适的索引

2  提取的数据占据整体表的数据量是少数或极少数

3  获取数据的字段在索引中,不需要回表找到索引中未包含的数据

4  Bitmap Scan 

Bitmap Scan 扫描的出现是基于获取的数据在 INDEX SCAN 中的问题点而产生的一个数据的获取的方式,在INDEX SCAN 中获取到数据的位置后,还是需要到对应的数据页面中,在扫描到对应的数据,而BITMAP SCAN 就是要解决数据通过索引定位后,在去原数据页面定位的问题,解决最后一公里的问题。

位图索引扫描:首先它从索引数据结构中获取所有索引数据,并创建所有TID的位图。为了简单理解,您可以认为这个位图包含所有页面的哈希(基于page no进行哈希),并且每个页面条目包含该页内所有偏移量的数组。

所以通过位图来获取数据的方式,速度更快,当然相对的付出的成本也更多一些。BITMAP  如果用一个粗略的方式来评价为什么会选择这样的方式来获取数据。

数据量多少 

index_scan (index_only_scan)  <  bitmap scan < Sequential Scan

5 TID Scan 

TID 数据扫描的方式,是一种特殊的数据扫描的方式,在常见的数据获取中,是没有选择这样的数据获取的方式,但他可以解决一些特殊场景的问题。

实际上这样的数据获取的模式就是在PG的数据查询中直接使用CTID 的方式来获取数据的物理位置上的数据。

postgres=# explain select * from table where ctid='(116,42)';

                       QUERY PLAN ---------------------------------------------------------- Tid Scan on demotable  (cost=0.00..4.01 rows=1 width=15)   TID Cond: (ctid = '(116,42)'::tid)

在我们清楚了相关的数据搜索的几种方式后,那么数据集合和集合之间的关系如何处理是我们下一个需要理解的部分,在POSTGRESQL 中我们可以将数据集合和数据集合之间的关系处理放方式。

1  Nested Loop join

2  Hash join 

3  Merge join

1   NLJ Nested loop join  ,嵌套循环,嵌套循环是将集合和集合之间的关系进行比较,在操作中,是两个集合比较的关系,将外部数据逐条的与内部的集合的数据进行匹配.

这种数据集合比较的方式,是比较消耗数据库运算性能的,在使用这样的方式进行数据库的连接的情况下应该采用驱动表尽量小的方式来进行数据的处理。

477b171ac8215927e8f8d8690ec81892.png

2  Hash join 

hash join 适用于集合和集合之间的等值比较,使用HASH JOIN 方式中的集合和集合之间的关系应该是等于的方式。下面的这个例子中,选择了 bt2 作为hash的表,将相关的数据先进行HASH 存储到内存中,在将bt1 中的数据hash后与hash表中的数据进行对比。显然这样的方式比第一个刚才提到的NLJ的方式要更快,但也有相关的限制条件,就是被HASH的部分可以放入到内存当中。

select * from table1 bt1, table2 bt2 where bt1.id1 = bt2.id1;

Hash Join  (cost=27.50..220.00 rows=1000 width=16)   Hash Cond: (bt1.id1 = bt2.id1)   ->  Seq Scan on table1 bt1  (cost=0.00..145.00 rows=10000 width=8)   ->  Hash  (cost=15.00..15.00 rows=1000 width=8)         ->  Seq Scan on table2 bt2  (cost=0.00..15.00 rows=1000 width=8) (5 rows)

3  Merge join 

Merge join  也是一种集合和集合之间的进行数据挑选的方式,在进行Merge join 的方式中,需要注意的是集合和集合之间的数据是需要进行排序的,也就是说如果要进行 Merge join 则在除了必须是 = 号运算的基础上,等号两边的的所在的列 ,必须是带有索引的,有序的。

postgres=# explain select * from table1 bt1, table2 bt2 where bt1.id1 = bt2.id1;                    QUERY PLAN ------------------------------------------------------------------------ Merge Join  (cost=0.56..90.36 rows=1000 width=16)   Merge Cond: (bt1.id1 = bt2.id1)   ->  Index Scan using idx1 on table1 bt1  (cost=0.29..318.29 rows=10000 width=8)   ->  Index Scan using idx2 on table2 bt2  (cost=0.28..43.27 rows=1000 width=8) (4 rows)

在说完这些后,细致的同学可能在执行计划中发现过如下的一些工作的项目

  • Sort

  • Aggregate

  • Group By Aggregate

  • Limit

  • Unique

  • LockRows

  • SetOp

1  sort , sort 有的时候有,有的时候没有,可能有些同学会发现这个问题,比如昨天我还发现我的执行计划里面有这个,今天我在用就没有了,这是什么原因,我们看下面两个部分,同样的语句,同样的配方,但是执行计划不同,因为在语句中都有 order by 但不同的是,因为后面的表创建了对应ORDER BY 字段的索引,所以不在需要进行显示的排序。

postgres=# explain select * from table order by num;                   QUERY PLAN ---------------------------------------------------------------------- Sort  (cost=819.39..844.39 rows=10000 width=15)   Sort Key: num   ->  Seq Scan on table  (cost=0.00..155.00 rows=10000 width=15) (3 rows)

postgres=# CREATE INDEX demoidx ON table(num); CREATE INDEX postgres=# explain select * from table order by num;                     QUERY PLAN ---------------------------------------------------------------------- Index Scan using demoidx on demotable  (cost=0.29..534.28 rows=10000 width=15) (1 row)

2 Aggregate   聚合操作是我们在SQL 执行计划中经常碰到的,这个操作的意味着你在语句的执行中有使用聚合函数,或对整体的结果进行了count 计算等等,一般对于SQL执行中出现使用进行汇总,分析的函数时都会出现这个聚合测操作。

3  GroupAggregate 和 hashAggregate 出现的情况下,意味着SQL 的操作中出现了 GROUP BY, 而如果是 groupAggregate 并且在此位置的 cost 较大的情况下,则说明进行group by 的字段没有索引的可能性较大.

postgres=# explain select count(*) from demo2 group by id2;                            QUERY PLAN ------------------------------------------------------------------------- GroupAggregate  (cost=9747.82..11497.82 rows=100000 width=12)   Group Key: id2   ->  Sort  (cost=9747.82..9997.82 rows=100000 width=4)      Sort Key: id2      ->  Seq Scan on demo2  (cost=0.00..1443.00 rows=100000 width=4) (5 rows)

postgres=# create index idx1 on demo1(id); CREATE INDEX postgres=# explain select sum(id2), id from demo1 where id=1 group by id;                            QUERY PLAN ------------------------------------------------------------------------ GroupAggregate  (cost=0.28..8.31 rows=1 width=12)   Group Key: id   ->  Index Scan using idx1 on demo1  (cost=0.28..8.29 rows=1 width=8)      Index Cond: (id = 1) (4 rows)

而hashAggregate 一般是结果较小,并且需要分组进行数据的展示的情况下,使用hashAggregate的方式进行处理。

postgres=# explain select count(*) from demo1 group by id2;                       QUERY PLAN --------------------------------------------------------------- HashAggregate  (cost=20.00..30.00 rows=1000 width=12)   Group Key: id2   ->  Seq Scan on demo1  (cost=0.00..15.00 rows=1000 width=4) (3 rows)

除以上的部分,还有如subquery scan ,setOp, lockrows, Unique 等这里就不在多说了。

5892468e3f23add85d8d7c23790f42e5.png

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Codeforces-Round-805-Div-3-E-Split-Into-Two-Sets

title: Codeforces Round 805 (Div. 3) E. Split Into Two Sets date: 2023-04-25 18:14:41 categories: AlgorithmCodeforces tags:codeforces并查集1600 E. Split Into Two Sets 题目大意 给你n组数&#xff0c;每组里面有两个数字&#xff0c;问你能不能把这n组数分为两组…

【数据架构系列-06】一文搞懂数据模型的3种类型——概念模型、逻辑模型、物理模型

数据模型就是模拟现实世界的方法论&#xff0c;是通向智慧世界的基石&#xff01; 从现实世界发展到智慧世界&#xff0c;要数经历现实世界、信息世界、计算机世界、数据世界、智慧世界五个不同的世界&#xff0c;我们天生具有从混沌的世界抽象信息变为信息世界的能力&#xff…

基于jenkinsfile布置java工程

需求 通过jenkins发布java项目到服务器 预备环境 项目地址&#xff1a; https://gitee.com/asaland/sb-docker-appJenkins 2.387.3 通过Jenkinsfile实现方式 jenkins ui 配置pipeline 什么是pipeline? 直接看注释吧&#xff0c;简单点就是编排可以多个跨时间的构建代理…

JavaScript全解析——canvas 绘制变换和渐变

绘制变换 ●在 cancas 内, 也可以向 css 中一样, 出现一些 2d 变换的效果 ●先来绘制一个基本矩形 // 0. 获取到页面上的 canvas 标签元素节点 const canvasEle document.querySelector(#canvas)// 1. 获取当前这个画布的工具箱 const ctx canvasEle.getContext(2d)// 2. 绘…

ip数据报计算首部检验和

当我们在使用互联网进行数据传输时&#xff0c;数据可能会被篡改或者损坏。为了保证数据传输的可靠性和完整性&#xff0c;计算IP数据包首部检验和是一种非常重要的校验机制。本文将会介绍计算IP数据包首部检验和的方法。 IP数据包首部 首先&#xff0c;我们需要了解IP数据包…

5 系统数据文件和信息

5.1 口令文件 口令文件包含了下表中所示的各字段&#xff0c;这些字段包含在<pwd.h>中定义的passwd结构中。 /etc/passwd文件中的字段 说 明struct passwd 成员用户名char *pw_name加密口令char *pw_passwd数值用户IDuid_t pw_uid数值组IDgid_t pw_gid注释字段char *pw_g…

Unity实现GPU Cull渲染

前言 开放世界游戏中植被和物件的数量往往是巨大, 而传统组织大量植被渲染的方式是利用QuadTree/Octree/Kd-Tree等数据结构对植被Intance数据进行预先生成一个个Cluster&#xff0c;然后在运行时进行FrustumCull,收集可视的所有Cluster&#xff0c;最后进行DrawInstance. 这…

Yolov1 源码讲解 loss.py

结构 1.lt rb我觉得不是很合适 正确来说是lb rt 因为比较出来的都是左下和右上坐标 比如前两个&#xff0c;都是max出来的 选两个box左下坐标中最大的&#xff0c; 后两个则是右上坐标中最小的 那也就形成了交集面积 但是代码中仍然是lt rb我也就直接这样说 而算出lt和r…

zynq基于XDMA实现PCIE X8视频采集HDMI输出 提供工程源码和QT上位机程序和技术支持

目录 1、前言2、我已有的PCIE方案3、基于zynq架构的PCIE4、总体设计思路和方案视频输入通路PCIE数据缓存通路视频输出通路 5、vivado工程详解6、SDK 工程详解7、驱动安装8、QT上位机软件9、上板调试验证10、福利&#xff1a;工程代码的获取 1、前言 PCIE&#xff08;PCI Expre…

二叉树的实现

二叉树 文章目录 二叉树背景二叉树的概念遍历方式代码实现 背景 数组存储方式的分析 优点&#xff1a;通过下标方式访问元素&#xff0c;速度快。对于有序数组&#xff0c;还可使用二分查找提高检索速度。 缺点&#xff1a;如果要检索具体某个值&#xff0c;或者插入值(按一…

linux中使用docker部署微服务

目录 一、制作jar包&#xff08;如果看一眼很简单&#xff0c;可以直接使用结尾的jar&#xff09; 1.首先创建一个微服务 demo2 2.启动微服务&#xff08;在DemoApplication上右键执行启动就行&#xff09; 注意&#xff1a;其他操作导致的 可能遇到的报错 3.修改端口 4.新…

ChatGPT的快速发展究竟给我们带来了什么?

&#x1f61a;一个不甘平凡的普通人&#xff0c;致力于为Golang社区和算法学习做出贡献&#xff0c;期待您的关注和认可&#xff0c;陪您一起学习打卡&#xff01;&#xff01;&#xff01;&#x1f618;&#x1f618;&#x1f618; &#x1f917;专栏&#xff1a;算法学习 &am…

java基础入门-05-【面向对象进阶(static继承)】

Java基础入门-05-【面向对象进阶&#xff08;static&继承&#xff09;】 13、面向对象进阶&#xff08;static&继承&#xff09;1.1 如何定义类1.2 如何通过类创建对象1.3 封装1.3.1 封装的步骤1.3.2 封装的步骤实现 1.4 构造方法1.4.1 构造方法的作用1.4.2 构造方法的…

Unity API详解——Random类

Random类是Unity中用于产生随机数的类&#xff0c;不可以实例化&#xff0c;只有静态属性和静态方法。本博客主要介绍了Random类的一些静态属性。 文章目录 一、Random类静态属性1、基本语法2、功能说明3、代码实现 二、rotationUniform属性1、基本语法2、功能说明1、规范化向量…

前沿探索,AI 在 API 开发测试中的应用

目录 一、引言二、AI 加持下的 API 设计1、NLP 在 API 设计中的应用2、DL 在 API 设计中的应用能力一&#xff1a;Apikit 如何利用 AI 生成最佳的 API 设计方案能力二&#xff1a; Apikit 如何利用 AI 提高 API 的可用性和易用性 三、AI 加持下的 API 开发能力三&#xff1a;Ap…

k8s二进制安装部署(详细)(3主2从)

目录 kubeadm 和二进制安装 k8s 适用场景分析 多 master 节点高可用架构图 集群环境准备 部署过程 修改主机内核参数&#xff08;所有节点&#xff09; 配置阿里云的repo源&#xff08;所有节点&#xff09; 配置国内安装 docker 和 containerd 的阿里云的 repo 源 配置…

比肩 ChatGPT,国内快速访问的强大 AI 工具 Claude

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;蚂蚁集团高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐…

Gateway案例

官网:Spring Cloud Gateway 中文文档:Spring Cloud Gateway 2.1.0 中文官网文档 - 腾讯云开发者社区-腾讯云 一、网关介绍: 网关就是当前微服务的统一入口 通常在微服务项目中,只有网关项目是暴露在网络里的,其他服务一般都是在内网里, 用户访问网关,网关根据访问的路径,来进…

Tomcat安装步骤及详细配置教程(2022最新版)

网上的tomcat安装及配置教程一大堆&#xff0c;但是好多都过时了&#xff0c;根本不适用现在的版本&#xff0c;今天凯歌整理一篇Tomcat安装步骤及详细配置教程&#xff0c;2022年最新版~ Tomcat安装及配置教程主要分为四步&#xff1a; 步骤一&#xff1a;首先确认自己是否已…

ChatGPT登录操作扫盲级教程,附ChatGPT登录常见报错及处理技巧

文 / 韩彬&#xff08;微信公众号&#xff1a;量子论&#xff09; 有了帐号&#xff0c;我们自然可以使用ChatGPT尽情玩耍了。 知识扩展&#xff1a;ChatGPT是啥&#xff0c;以及注册的问题&#xff0c;可以看《ChatGPT常见问题手册&#xff0c;通俗易懂版&#xff0c;3分钟了解…