PostgreSql 执行计划

342 阅读3分钟

小知识,大挑战!本文正在参与“  程序员必备小知识  ”创作活动
本文同时参与 「掘力星计划」  ,赢取创作大礼包,挑战创作激励金

查看执行计划

explain (analyze true|false,verbose true|false,costs true|false,buffers true|false,format text|xml|json|yaml)
  • analyze:真实执行sql获取执行计划,dml语句不想改变数据库数据可放入事务,执行完后回滚,该选项默认值为false。
  • verbose:用于显示计划的附加信息,附加信息有计划熟中每个节点输出的各个列,如果触发器被触发,还会输出触发器的名称,该选项默认值为false。
  • costs:显示每个计划节点的启动成本和总成本,以及估计行数和每行宽度,该选项默认值为true。
  • buffers:显示关于缓冲器使用的信息,只能与analyze参数一起使用,显示的缓冲区信息包括共享块、本地块、临时块的读写块数,表、索引、临时表、临时索引及排序和物化计划中使用的磁盘块,上层节点使用的块数包含所有节点使用的块数。该选项默认值为false。
  • format:指定数据格式,可以是text、xml、json、yaml,默认值为text。

执行计划结果解释

chis=# explain select * from comm.account;
                          QUERY PLAN
--------------------------------------------------------------
 Seq Scan on account  (cost=0.00..106.54 rows=2454 width=225)
(1 row)
  • Seq Scan on account:表示顺序扫描(全表扫描)表account。
  • cost:后面的两个数字中间由..分隔,第一个数字0.0表示启动成本,也就是返回第一行需要多少成本,第二个数字106.54表示返回所有数据成本。
  • rows:返回行数。
  • width:表示每行平均宽度,单位字节。

cost 成本解释

  • 顺序扫描一个数据块,cost 值定为1。
  • 随机扫描一个数据块,cost 值定为4。
  • 处理一个数据行的 CPU,cost 值定为0.01。
  • 处理一个索引行的 CPU,cost 值定为0.005。
  • 每个操作符的 CPU 代价为 0.0025。

执行计划路径方式

  • 全表扫描(顺序扫描):seq scan,所有数据块,从头扫到尾。
  • 索引扫描:index scan,在索引中找到数据行的位置,然后到表的数据块中把对应的数据读出。
  • 位图索引扫描:bitmap index scan,把满足条件的行或块在内存中建一个位图,扫描完索引后,再根据位图把表的数据文件中相应的数据读取出来。
  • 条件过滤:filter
  • 嵌套循环连接:nestloop join,外表(驱动表)小,内表(被驱动表)大
  • 散列连接:hash join,用较小的表在内存中建立散列表,再去扫描较大的表,连接的表均为小表。
  • 合并连接:merge join,通常散列连接比合并连接性能好,当有索引或结果已经被排序时,合并连接性能好。

临时改变执行计划(类似 oracle 的 hint 干预执行计划,pg也有 pg_hint 插件,后期再研究)

通常情况下,pg 不会走错执行计划,走错大都是因为统计信息收集不及时导致的,可通过更频繁地运行 analyze 来解决这个问题,更改下列参数只是一个临时方法。(如下参数值均为布尔类型)

  • enable_seqscan:是否选择全表顺序扫描,把这个变量关闭会让优化器存在其他方法时,优先选择其他方法。
  • enable_indexscan:是否选择索引扫描。
  • enable_bitmapscan:是否选择位图扫描。
  • enable_tidscan:是否选择位图扫描。
  • enable_nestloop:多表连接时,是否选择嵌套循环连接。
  • enable_hashjoin:多表连接时,是否选择 hash 连接。
  • enable_mergejoin:多表连接时,是否选择 merge 连接。
  • enable_hashagg:是否使用 hash 聚合。
  • enable_sort:是否选择排序。