广告
返回顶部
首页 > 资讯 > 数据库 >Postgresql执行计划概述
  • 567
分享到

Postgresql执行计划概述

Postgresql执行计划概述 2021-11-01 15:11:57 567人浏览 绘本
摘要

  执行计划个人理解是一个“点”,“线”,“面”的问题,关系数据库中执行计划是一个同质化的对象,串联起来还是比较容易掌握的,对于一条复杂的sql,所谓的点就是其中单个表的访问方式,线是表之间的连接驱动顺序,面就是表与表之间的具体连

Postgresql执行计划概述

 

执行计划个人理解是一个“点”,“线”,“面”的问题,关系数据库中执行计划是一个同质化的对象,串联起来还是比较容易掌握的,对于一条复杂的sql,所谓的点就是其中单个表的访问方式,线是表之间的连接驱动顺序,面就是表与表之间的具体连接算法以及中间结果在内存缓冲区中的处理(类似于bitmap scan,中间结果集的buffer处理等等),这样一来,一个sql就的执行计划就可以逐步拆解开来,可以逐个基于细节来分析。postgresql的执行计划,整体上看跟Mysql或者sqlserver都是差不多的,但Postgresql对执行计划在细节上的描述还是很粗糙的,索引的访问形式来说:mysql中有index 遍历索引/range 索引范围查找/ref 非唯一索引查找数据/eq_ref 非唯一索引查找数据,以及回表的标记;sqlserver中也存在着scan和seek是两个完全不同的概念,以及明显的“回表”标记。在postgresql执行计划中是无法直接体现出来的,全部称之为index scan(index only scan),这一点说实话是比不上MySQL或者sqlserver的,后两者对执行计划的描述都很细化。

1 执行计划中的“点”

1.1 顺序扫描Seq Scan

顺序扫描实际上就是全表扫描,没有任何可用索引或者不适合走索引的情况下的一种查询行为 seq scan的图形化示例

1.2 索引扫描IndexScan

通过访问索引获得元组位置指针后再访问表数据本身,index scan实际上是包含了通过索引键值查找,然后“回表”的过程,这个执行计划或者字面上,都没有体现出来。

index scan的图形化示例

1.3 Index Only Scan

如果索引scan不需要回表的话,执行计划如果表达这种逻辑?
对于 index scan,如果一个查询不需要回表的场景,比如select c1 from table where c1 =100;查询的列在索引中就可以直接得到,无需回到基表去得到其他字段,这种执行计划叫做Index Only Scan
相比index scan,index only scan就是去掉“回表”这个过程,仅在索引树上就可以完成的查询

1.4 位图索引扫描Bitmap Index Scan

bitmap index scan的详细介绍见这里:https://www.cnblogs.com/wy123/p/13376991.html
bitmap的图形化示例,其中包含了两部分,第一是bitmap的生成过程,第二是多个bitmap之间的与(或)操作后排序,然后回表的过程。

1.5 预期的index only scan没有出现

由于Index Only Scan表示仅需要索引就可以找到所需要的数据,无需回表,那么同样在无需回表的情况下,postgresql如何区分对索引树(b+)树的查找(真正的二分法查找)和扫描(扫描整颗B+树)?这个是一个有意思的问题,这里刻意创建一个抑制索引使用的但是无需回表的查询: select c2 from myschema.table_test where c2+1 = 1001;,
看看会发生什么,这也是笔者在一开始想不明白的一个问题,它竟然总的是走了一个全表扫描???

从postgresql 11版本测试到最新的postgresql 12最新版,表中的数据里从十万级测试到千万级,都是这么一个全表扫描的执行计划,搜遍全网都没有发现对这个问题合理的解释,或许用postgresql的人都比较注意sql的规范性从而避免索引被抑制的写法,但是为什么这里需要“回表”? 对于这个查询,可以肯定的是,索引树的大小(size)是肯定小于基表的堆结构的,即便是无法直接使用到索引,但是扫描整个索引树的代价是远远小于整个基表的,最后还是从官方文档中发现这个对这个问题的解释,真相还是有点意外。
这两个问题虽然不完全相同,但还是有一些类似的地方,看来postgresql一些优化措施还是有进步空间的,说白了,官方就是说优化器不够智能,无法识别类似情况,只能做全表扫描来实现。理论上说是可以index only scan完成的操作,为什么会出现seq scan? 其实这个并不难理解,当where条件时c+1 = 1001的时候,因为c+1 并不是一个直接可用的索引字段,优化器并不知道这个表达式经过计算后可以转换成一个索引字段,因此会走全表扫描。至此,postgresql中仅从索引就可以得到查询结果的情况下,如何区分对索引树的二分法查找和索引树扫描?
除此之外,对于其他关系数据库中的select count(1) from table语句的优化,往往可以在一个长度较小的字段上建立一个索引,然后查询就自动遍历这个索引来获取总行数的优化思路。
在Postgresql中是行不通的,类似查询Postgresql中并不会扫描一个较小的二级索引来实现count计算,而依旧走的是一个全面扫描。
这一点查阅相关资料说是与Postgresql的mvcC,事物可见性映射有关,也就是说在统计表中总行数的时候还要判断遍历的行数是不是对当前行可见的。参考这里,个人觉得其实并没有说清楚。 类似select count(1) from table;没有任何where条件下,默认一直是走seq scan table 的,究竟如何与事物的可见性关联起来的?
事务可见性以及MVCC,这一点还是比较有搞头的,埋个坑先:
因为事务的可见性只在数据行中标记,对索引是不生效的,难道说通过二级索引回表找到的记录,都要进行一次可见性判断?
Https://www.postgresql.org/docs/9.4/index-scanning.html
https://www.postgresql.org/docs/current/storage-vm.html

2 执行计划中的“线

相对MySQL处理复杂sql能力相对较弱(被吐槽较多的子查询,尽管MySQL一直在改进他的执行计划算法),不太适合相对复杂的sql查询的场景,postgresql宣称能够处理复杂的sql查询,其实都是其背后的算法决定的。
相比MySQL执行计划连接路径的贪心算法,其最大的问题在于只关心局部,而不关心整体,可能每一步都是最优解,但最终可能不是最优解的情况。
postgresql采用动态规划算法和遗传算法结合起来生成执行计划,理论上说postgresql的执行计划生成算法是更加优秀的。
类似图的最短路径算法,比如从1到5的最短路径: 1,对于贪心算法来说,会走1-》2=》3=》5的路径,当前的每一步都是最优解,整体上看并不是最优解。
2,对于动态规划算法来说,会走1=》4=》3=》5的路径,其代价明显优于贪心算法的结果。
贪心算的问题潜在的问题很明显,最终的解很可能不是最优的,尽管MySQL在这方面一直在改进。
对于动态规划算法可以遍历所有路径来获取一个最短路径,这种算法在节点数超过一定程度之后的时间复杂度会呈指数级增长,因此postgresql也会采用折中一些的遗传算法来实现(类似遗传基因改良过程,逐渐退化掉不好的部分)。
不管是贪心算法,还是动态规划算法,遗传算法,其本身各有优缺点:
前者实现简单,时间复杂度低,但存在非最优解的情况;
后者尽管可以得到最优解,但是其时间复杂度要大于贪心算法。
同时也不难理解,为什么MySQL发展至今中没有执行计划缓存? 就是因为其在相对简单的场景下,执行计划的生成代价相对较小,因此考虑可以不缓存执行计划,可以临时性编译,贪心算法同时也决定了MySQL不太适合处理相对复杂的sql查询场景,
其实这恰恰吻合了互联网项目短平快的特点么,所以MySQL适合这一套,有点野路子的风格(话说mysql的出身就比较野路子)。 而postgresql执行计划的访问路径生成代价相对较高,对于复杂的sql查询每次编译代价相对较大,因此就保留了执行计划缓存从而达到可重用的目的(pg_prepared_statements),这是典型的学院派的风格。

3 执行计划中的“面”

3.1 join方式

这里的“面”是表与表之间的连接处理方式,其实就是经典的loop join,merge join,hash join这三种join方式。
postgresql中的三种join方式与其他数据库的join在思路上并无二致,原理也很简单,基本上都有各自适合的场景和前提条件。

1.1 loop join
适合处理两个较小的结果集的场景,同时,尽管是较小的结果集,在有索引驱动的情况下loop join的效率也会相对较高,第二个图例就代表着基于索引驱动的loop join

1.2 merge join
适合处理两个有序结果集的场景,或者jion双方本身存在一致的索引键
相比loop join只有outer表会前推,merge join在join的时候,outer和inner表同时有一个“前推”的过程,也就是说随着join的进行,outer表的键对inner表的探测次数会越来越少。
要清楚,outer table和inner table的有序是merge join的因,而非果。

1.3,hash join
对于无索引且结果集较大的场景,属于重量级的查询处理。
其实平时不得见经常出现hash join,如果一个系统的查询中经常出现hash join,也不见得是一件好事,在前面两种足够“轻量级”join方式处理不动时的一种选择。
相比以上两种join方式,hash join可能较为难理解一点:hash join简单说分两个阶段,第一个阶段是构建hash桶,对join双方较小的一个表的连接键生成hash桶,第二个阶段是对join的另外一张表的键值基于hash运算后进行探测。
为什么要这么做?其实还是跟“join条件上没有索引有关”,相当于间接性地生成了一个hash索引,因此这种情况适合join双方都变较大,且没有索引的场景。
那么,为什么在重量级的join情况下为什么不加索引呢,所以上面也说了,经常看到hash join并不代表什么好现象,而是一种不得已的选择。

并行查询

并行查询可以应用在绝大多数上述的点线面中
比如并行Seq Scan,并行Index Scan,并行join等等,其目的就是多个CPU协同工作,然后汇总的一种思路,这一点postgresql还是比较给力的,当然也不是并行线程数越多越好(max_parallel_workers)。

强制查询提示

查询提示作为优化的debug作用,可以尝试强制按照非默认的执行方式来对比,参考这里:https://blog.csdn.net/jackGo73/article/details/89711523

 

以上截图这些有趣的图片来自于:https://momjian.us/main/writings/pgsql/internalpics.pdf

您可能感兴趣的文档:

--结束END--

本文标题: Postgresql执行计划概述

本文链接: https://www.lsjlt.com/news/7576.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Postgresql执行计划概述
      执行计划个人理解是一个“点”,“线”,“面”的问题,关系数据库中执行计划是一个同质化的对象,串联起来还是比较容易掌握的,对于一条复杂的sql,所谓的点就是其中单个表的访问方式,线是表之间的连接驱动顺序,面就是表与表之间的具体连...
    99+
    2021-11-01
    Postgresql执行计划概述
  • 【PG执行计划】Postgresql数据库执行计划统计信息简述
    --添加analyze实际执行来获得执行计划,可不加 explain analyze select * from test_table; --只...
    99+
    2022-10-18
  • Postgresql统计信息概述
      对于sql优化,除了索引之外,执行计划和统计信息是无法绕开的一个话题,如果sql优化(所有的RDBMS)脱离了统计信息的话就少了一个为什么的过程,味道就感觉少了一大半。刚接触Postgresql,粗浅地学习总结一下Postgr...
    99+
    2017-07-30
    Postgresql统计信息概述
  • 执行计划-1:获取执行计划
    看懂执行计划是作为处理数据库性能问题的必备技能之一,接下来一系列的文章我 会告诉你怎么去做。 我们会从一些文章开始讨论几种获取执行计划的方法,并且评估不同来源的执行计划最适合哪种场景。 完成上述的内容后我...
    99+
    2022-10-18
  • oracle sqlprofile 固定执行计划,并迁移执行计划
    sqlprofile固定执行计划 模拟10g 执行计划迁移至11g oracle数据库中,11g库用10g的执行计划,这里是把hint 全盘扫描的执行计划迁移  --1.准备阶段&nb...
    99+
    2022-10-18
  • 读懂执行计划
    查看执行计划的方法 Explain Plan For SQL• 不实际执行SQL语句,生成的计划未必是真实执行的计划• 必须要有plan_table是一种手段但不是最好的 SQLPLUS AUTOTRAC...
    99+
    2022-10-18
  • 执行计划绑定
    http://www.mamicode.com/info-detail-1943333.html 需要绑定SQL执行计划常见的几种情况: SQL执行计划突变,导致数据库性能下降,从历史执行计划找一个合理...
    99+
    2022-10-18
  • MySQL 5.7Explain执行计划
    小编给大家分享一下MySQL 5.7Explain执行计划,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!目录1. 介绍2. Ex...
    99+
    2022-10-18
  • SQLServer的执行计划
    目录一、背景二、显示和保存执行计划三、显示估计的执行计划四、显示实际执行计划五、以 XML 格式保存执行计划六、比较和分析执行计划6.1、比较执行计划6.2、分析实际执行计划总结一、...
    99+
    2023-05-16
    SQL Server执行计划 SQL Server 执行计划
  • PostgreSQL DBA(13) - 自顶往下的方法阅读执行计划
    一般来说,阅读执行计划通常采用自底往上的方法,这好比从树的某片叶子出发然后再到树枝再到树干、树根这么一种方法来了解一颗树,这种方法存在的问题是如果这颗树很大,那么就可能出现“只见叶...
    99+
    2022-10-18
  • Oracle查询执行计划
    执行计划(Execution Plan)也叫查询计划(Query Plan),它是数据库执行SQL语句的具体步骤和过程。SQL查询语句的执行计划主要包括: ● 访问表的方式。数据库通过索引或全表扫描等方式访问表中的数据。...
    99+
    2023-04-03
    Oracle查询执行计划 Oracle执行计划查询
  • Oracle执行计划绑定
    有时我们查询 gv$sql可以看出同一个SQL不同子游标的一些运行细节: selet t.inst_id,t.sql_id,t.child_number,t.plan_hash_value,t.last_...
    99+
    2022-10-18
  • 详解 MySQL 执行计划
    EXPLAIN语句提供有关MySQL如何执行语句的信息。EXPLAIN与SELECT,DELETE,INSERT,REPLACE和UPDATE语句一起使用。 EXPLAIN为SELECT语句中使用的每个表返回...
    99+
    2022-05-10
    MySQL 执行计划
  • MySQL执行计划详解
    一、mysql执行计划介绍 在MySQL中,执行计划的实现是基于JOIN和QEP_TAB这两个对象。其中JOIN类表示一个查询语句块的优化和执行,每个select查询语句(即Query_block对象)在处理的时候,都会...
    99+
    2022-09-28
  • oracle执行计划解释
    (1).explain plan命令(不准)explain plan for select语句select * from table(dbms_xplan.display);(2).DBMS_XP...
    99+
    2022-10-18
  • 看懂Oracle执行计划
    一:什么是Oracle执行计划? 执行计划是一条查询语句在Oracle中的执行过程或访问路径的描述 二:怎样查看Oracle执行计划? 因为我一直用的PLSQL远程连接的公司数据库,所...
    99+
    2022-10-18
  • mongodb 执行计划说明
    创建documents:for (i=0;i<1000000;i++){db.users.insert({"i":i,"username":"user...
    99+
    2022-10-18
  • explain执行计划分析
    告诉我们mysql优化器是怎样处理我们的sql请求的并不是说在相关查询列上有索引,mysql在查询时就能使用到,虽然我们认为适合,但mysql优化器不一定这样认为mysql并不一定根据我们sql语句中的顺序...
    99+
    2022-10-18
  • oracle 固定执行计划
    ---chenjch ...
    99+
    2022-10-18
  • mysql如何执行计划
    小编给大家分享一下mysql如何执行计划,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!      ...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作