PG数据库中的EXPLAIN用法

一、EXPLAIN语法

EXPLAIN命令的主要作用是输出一个query的整个查询计划,具体语法如下:

EXPLAIN [ ( option [, ...] ) ] statement
EXPLAIN [ ANALYZE ] [ VERBOSE ] statementwhere option can be one of:ANALYZE [ boolean ]VERBOSE [ boolean ]COSTS [ boolean ]BUFFERS [ boolean ]TIMING [ boolean ]SUMMARY [ boolean ]FORMAT { TEXT | XML | JSON | YAML }

我只介绍用到的,后面再慢慢补充吧。。。。

  1. ANALYZE :选项默认为true,会把query实际执行一遍。
  2. 这篇文章写的挺好的: 文章
  3. pg11之后增加了并行功能:并行

二、EXPLAIN的输出结构

explain命令的输出可以看做是一个树形结构-查询计划树,树的每个节点包含对应的节点类型,作用对象以及其他属性如cost,rows,width等。
例如:

EXPLAIN ANALYZE SELECT *
FROM tenk1 t1, tenk2 t2
WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2 ORDER BY t1.fivethous;QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------Sort  (cost=717.34..717.59 rows=101 width=488) (actual time=7.761..7.774 rows=100 loops=1)Sort Key: t1.fivethousSort Method: quicksort  Memory: 77kB->  Hash Join  (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)Hash Cond: (t2.unique2 = t1.unique2)->  Seq Scan on tenk2 t2  (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)->  Hash  (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)Buckets: 1024  Batches: 1  Memory Usage: 28kB->  Bitmap Heap Scan on tenk1 t1  (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)Recheck Cond: (unique1 < 100)->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=101 width=0) (actual time=0.049..0.049 rows=100 loops=1)Index Cond: (unique1 < 100)Planning time: 0.194 msExecution time: 8.008 ms

可化简为:

Sort
└── Hash Join├── Seq Scan└── Hash└── Bitmap Heap Scan└── Bitmap Index Scan

在PG中实际的查询是从下往上执行的,基于火山模型?(每个节点返回一行记录给父节点)。其实EXPLAIN 输出的就是一个用户可视化的查询计划树,可以告诉我们执行了哪些节点(操作),并且每个节点(操作)的代价预估是什么样的。接下来,我们将详细去阐述每个节点的类型和具体干了哪些事情。

节点类型

  1. 控制节点
  2. 扫描节点
  3. 物化节点
  4. 连接节点

扫描节点

扫描节点简单来说就是为了扫描表的元组,每次获取一条元组作为上层节点的输入。当然严格的说,不光可以扫描表,还可以扫描函数的结果集、链表结构、子查询结果集等。

Seq Scan,顺序扫描
Index Scan,基于索引扫描,但不只是返回索引列的值
IndexOnly Scan,基于索引扫描,并且只返回索引列的值,简称为覆盖索引
BitmapIndex Scan,利用Bitmap 结构扫描
BitmapHeap Scan,把BitmapIndex Scan 返回的Bitmap 结构转换为元组结构
Tid Scan,用于扫描一个元组TID 数组
Subquery Scan,扫描一个子查询
Function Scan,处理含有函数的扫描
TableFunc Scan,处理tablefunc 相关的扫描
Values Scan,用于扫描Values 链表的扫描
Cte Scan,用于扫描WITH 字句的结果集
NamedTuplestore Scan,用于某些命名的结果集的扫描
WorkTable Scan,用于扫描Recursive Union 的中间数据
Foreign Scan,用于外键扫描
Custom Scan,用于用户自定义的扫描

Seq Scan

是全表顺序扫描,一般查询没有索引的表需要全表顺序扫描,例如下面的EXPLAIN 输出:

postgres=> explain(ANALYZE,VERBOSE,BUFFERS) select * from class where st_no=2;QUERY PLAN
--------------------------------------------------------------------------------------------------------Seq Scan on public.class  (cost=0.00..26.00 rows=1 width=35) (actual time=0.136..0.141 rows=1 loops=1)Output: st_no, nameFilter: (class.st_no = 2)Rows Removed by Filter: 1199Buffers: shared hit=11Planning time: 0.066 msExecution time: 0.160 ms

其中:

  1. Seq Scan on public.class 表明了这个节点的类型和作用对象,即在class 表上进行了全表扫描
  2. (cost=0.00…26.00 rows=1 width=35) 表明了这个节点的代价估计,这部分我们将在下文节点代价估计信息中详细介绍
  3. (actual time=0.136…0.141 rows=1 loops=1) 表明了这个节点的真实执行信息,当EXPLAIN 命令中的ANALYZE选项为on时,会输出该项内容,具体的含义我们将在下文节点执行信息中详细介绍
  4. Output: st_no, name 表明了query的输出结果集的各个列,当EXPLAIN 命令中的选项VERBOSE 为on时才会显示
  5. Filter: (class.st_no = 2) 表明了Seq Scan 节点之上的Filter 操作,即全表扫描时对每行记录进行过滤操作,过滤条件为class.st_no = 2
  6. Rows Removed by Filter: 1199 表明了过滤操作过滤了多少行记录,属于Seq Scan 节点的VERBOSE 信息,只有EXPLAIN 命令中的VERBOSE 选项为on 时才会显示
  7. Buffers: shared hit=11 表明了从共享缓存中命中了11 个BLOCK,属于Seq Scan 节点的BUFFERS 信息,只有EXPLAIN 命令中的BUFFERS 选项为on 时才会显示
  8. Planning time: 0.066 ms 表明了生成查询计划的时间
  9. Execution time: 0.160 ms 表明了实际的SQL 执行时间,其中不包括查询计划的生成时间

Index Scan

Index Scan 是索引扫描,主要用来在WHERE 条件中存在索引列时的扫描,如上面Seq Scan 中的查询如果在st_no 上创建索引,则EXPLAIN 输出如下:

postgres=> explain(ANALYZE,VERBOSE,BUFFERS) select * from class where st_no=2;QUERY PLAN
------------------------------------------------------------------------------------------------------------------------Index Scan using no_index on public.class  (cost=0.28..8.29 rows=1 width=35) (actual time=0.022..0.023 rows=1 loops=1)Output: st_no, nameIndex Cond: (class.st_no = 2)Buffers: shared hit=3Planning time: 0.119 msExecution time: 0.060 ms
(6 rows)

其中:

  1. Index Scan using no_index on public.class 表明是使用的public.class 表的no_index 索引对表进行索引扫描的
  2. Index Cond: (class.st_no = 2) 表明索引扫描的条件是class.st_no = 2
    可以看出,使用了索引之后,对相同表的相同条件的扫描速度变快了。这是因为从全表扫描变为索引扫描,通过Buffers: shared hit=3 可以看出,需要扫描的BLOCK(或者说元组)少了,所以需要的代价也就小了,速度也就快了。

IndexOnly Scan

IndexOnly Scan 是覆盖索引扫描,所需的返回结果能被所扫描的索引全部覆盖,例如上面Index Scan中的SQL 把“select * ” 修改为“select st_no” ,其EXPLAIN 结果输出如下:

postgres=> explain(ANALYZE,VERBOSE,BUFFERS) select st_no from class where st_no=2;QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------Index Only Scan using no_index on public.class  (cost=0.28..4.29 rows=1 width=4) (actual time=0.015..0.016 rows=1 loops=1)Output: st_noIndex Cond: (class.st_no = 2)Heap Fetches: 0Buffers: shared hit=3Planning time: 0.058 msExecution time: 0.036 ms
(7 rows)

其中:

  1. Index Only Scan using no_index on public.class 表明使用public.class 表的no_index 索引对表进行覆盖索引扫描
  2. Heap Fetches 表明需要扫描数据块的个数。

BitmapIndex Scan 与BitmapHeap Scan

BitmapIndex Scan 与Index Scan 很相似,都是基于索引的扫描,但是BitmapIndex Scan 节点每次执行返回的是一个位图而不是一个元组,其中位图中每位代表了一个扫描到的数据块。而BitmapHeap Scan一般会作为BitmapIndex Scan 的父节点,将BitmapIndex Scan 返回的位图转换为对应的元组。这样做最大的好处就是把Index Scan 的随机读转换成了按照数据块的物理顺序读取,在数据量比较大的时候,这会大大提升扫描的性能。
我们可以运行set enable_indexscan =off; 来指定关闭Index Scan ,上文中Index Scan 中SQL 的EXPLAIN 输出结果则变为:

postgres=> explain(ANALYZE,VERBOSE,BUFFERS) select * from class where st_no=2;QUERY PLAN
-----------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on public.class  (cost=4.29..8.30 rows=1 width=35) (actual time=0.025..0.025 rows=1 loops=1)Output: st_no, nameRecheck Cond: (class.st_no = 2)Heap Blocks: exact=1Buffers: shared hit=3->  Bitmap Index Scan on no_index  (cost=0.00..4.29 rows=1 width=0) (actual time=0.019..0.019 rows=1 loops=1)Index Cond: (class.st_no = 2)Buffers: shared hit=2Planning time: 0.088 msExecution time: 0.063 ms
(10 rows)

其中:

  1. Bitmap Index Scan on no_index 表明使用no_index 索引进行位图索引扫描
  2. Index Cond: (class.st_no = 2) 表明位图索引的条件为class.st_no = 2
  3. Bitmap Heap Scan on public.class 表明对public.class 表进行Bitmap Heap 扫描
  4. Recheck Cond: (class.st_no = 2) 表明Bitmap Heap Scan 的Recheck操作 的条件是class.st_no = 2,这是因为Bitmap Index Scan 节点返回的是位图,位图中每位代表了一个扫描到的数据块,通过位图可以定位到一些符合条件的数据块(这里是3,Buffers: shared hit=3),而Bitmap Heap Scan 则需要对每个数据块的元组进行Recheck
  5. Heap Blocks: exact=1 表明准确扫描到数据块的个数是1

一般来说:

  1. 大多数情况下,Index Scan 要比 Seq Scan 快。但是如果获取的结果集占所有数据的比重很大时,这时Index Scan 因为要先扫描索引再读表数据反而不如直接全表扫描来的快。
  2. 如果获取的结果集的占比比较小,但是元组数很多时,可能Bitmap Index Scan 的性能要比Index Scan 好。
  3. 如果获取的结果集能够被索引覆盖,则Index Only Scan 因为不用去读数据,只扫描索引,性能一般最好。但是如果VM 文件未生成,可能性能就会比Index Scan 要差。

PG数据库中的EXPLAIN用法相关推荐

  1. full join 和full outer join_带你了解数据库中JOIN的用法

    前言 欢迎关注公众号:Coder编程 获取最新原创技术文章和相关免费学习资料,随时随地学习技术知识! 本章主要介绍数据库中Join的的用法,也是我们在使用数据库时非常基础的一个知识点.本次会介绍数据库 ...

  2. mysql in从数据库取数_MySQL数据库中 where in 用法详解

    本文主要向大家介绍了MySQL数据库中 where in 用法详解,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. 这里分两种情况来介绍 WHERE column IN (valu ...

  3. 数据库中top的用法

    转自:微点阅读(www.weidianyuedu.com)微点阅读 - 范文大全 - 免费学习知识的网站 数据库中top的用法的用法你知道吗?下面小编就跟你们详细介绍下数据库中top的用法的用法,希望 ...

  4. mysql 中default什么意思_数据库中default的用法正确使用方法

    数据库中default的用法的正确使用方法你清楚吗,今天学习啦小编就跟大家详细介绍下数据库中default的用法,希望能帮到大家. 数据库中default的用法的用法 SQL Server数据库def ...

  5. 数据库中sum的用法浅述

    转自:微点阅读  https://www.weidianyuedu.com 数据库中sum的用法的用法你知道吗?下面小编就跟你们详细介绍下数据库中sum的用法的用法,希望对你们有用. 数据库中sum的 ...

  6. top在mysql中的意思_数据库中top的用法

    数据库中top的用法的用法你知道吗?下面小编就跟你们详细介绍下数据库中top的用法的用法,希望对你们有用. 数据库中top的用法的用法如下: 在编写程序中,我们可能遇到诸如查询最热门的5篇文章或返回满 ...

  7. 说说数据库中sum的用法

    转载自品略图书馆 http://www.pinlue.com/article/2020/03/3100/0210073883113.html 数据库中sum的用法的用法你知道吗?下面小编就跟你们详细介 ...

  8. Oracle数据库中SQL语句用法(一)

    Copyright © 2019 @Linyer. All Rights Reserved 下接Oracle数据库中SQL语句用法(二)[点击以查看] 目录 第1章:编写基本的SQL SELECT语句 ...

  9. 数据库中sum的用法

    转自:微点阅读(www.weidianyuedu.com)微点阅读 - 范文大全 - 免费学习知识的网站 数据库中sum的用法的用法你知道吗?下面小编就跟你们详细介绍下数据库中sum的用法的用法,希望 ...

最新文章

  1. LabVIEW图像灰度测量(基础篇—7)
  2. 跨链原子互换时代来临,BCH潜力无限!
  3. Python Model : glob 文件路径查找
  4. HDU 1561 The more, The Better
  5. Jackson学习笔记
  6. 蜘蛛搜索引擎_SEO:搜索引擎蜘蛛要引导,不能佛系优化
  7. w550官方例程_急!求索爱w550的刷机所需要的所有文件! 全部分送上!
  8. Django实现发邮件
  9. javax.net.ssl.SSLException: closing inbound before receiving peer‘s close_notif---SpringCloud工作笔记111
  10. easymock使用方法_EasyMock无效方法– ExpectLastCall()
  11. XML Schema 简介
  12. 中科院分区基础版和升级版究竟有何区别?
  13. MATLAB常用的滤波函数比较:均值滤波 和 中值滤波
  14. 鼠标不显示玩家服务器,远程链接服务器鼠标不显示
  15. 何凯明深度残差网络翻译
  16. csgo控制台服务器信息,《csgo》国服控制台怎么打开 控制台指令设置方法
  17. 哔哩哔哩如何提取封面_如何提取封面
  18. vmware workstation Pro 16使用ghost镜像安装windows11
  19. 网页数据获取小技巧(小白)
  20. intellij idea 2016破解方法

热门文章

  1. ASCII码与Unicode编码
  2. Maven安装配置和私服搭建
  3. JSP+Servlet java在线投票系统
  4. sql 同一个字段先按字母排序 再按数字排序
  5. 点石互动--kyw之:Matt Cutts语录
  6. Doubly Right Object Recognition: A Why Prompt for Visual Rationales
  7. 多个excel合并软件
  8. SIGIR‘21|SGL基于图自监督学习的推荐系统
  9. 适用于Web开发人员的20个CSS调色板
  10. 整合MGB实现CRUD以及各种姿势查询