小知识,大挑战!本文正在参与“ 程序员必备小知识 ”创作活动
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金
查看执行计划
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:是否选择排序。