postgresql中,利用explain 结合一些选项,如analyze、buffers等命令查看sql语句执行计划在一般场景下已经足够,但是基于如下原因,auto_explain将是一个强有力的补充:
鉴于pg优化器的复杂性,以及柱状图不同值数据的分布,sql不总是按照我们使用explain工具看到的执行计划执行
对于procedure/function执行计划的分析,通常我们可以raise notice查看各个sql的时间,也可以使用explain一段一段的查看执行计划,但是在procedure/function中往往有者复杂的写法,如for loop循环,要查看这些执行情况变得相当不容易
我们今天将仅演示auto_explain的使用,细节将可以查看postgresql官方文档auto_explain
auto_explain是一个session级的library,可以在使用时动态加载
set session_preload_libraries to auto_explain
load 'auto_explain'
参数具体含义可参考官方文档
set auto_explain.sample_rate = 1
set auto_explain.log_min_duration = 0
set auto_explain.log_analyze = true
set auto_explain.log_nested_statements to on
测试表t1
create table t1 (id bigint)
测试表t2
create table t2 (id bigint)
insert into t2 values(generate_series(1,10000))
create index idx_t2_id on t2(id)
create or replace function pro_test1()
returns record
LANGUAGE 'plpgsql'
as $body$
declare
v_num int :=1;
sfc record;
begin
delete from t1;
for sfc in (select id from t2 where id >9997)
loop
insert into t1(id) select * from t2 where sfc.id=t2.id;
end loop;
return sfc;
end;
$body$;
select pro_test1()
2023-06-27 13:53:42.728 WIB,"dbas","pccwms502Zdb",105829,"172.19.6.187:1032",649a5d9e.19d65,15056,"SELECT",2023-06-27 10:55:10 WIB,43/1567572,840415340,LOG,00000,"duration: 0.048 ms plan:
Query Text: delete from t1
Delete on t1 (cost=0.00..1.05 rows=5 width=6) (actual rows=0 loops=1)
-> Seq Scan on t1 (cost=0.00..1.05 rows=5 width=6) (actual rows=5 loops=1)",,,,,"SQL statement ""delete from t1""
PL/pgSQL function pro_test1() line 6 at SQL statement",,,,"pgAdmin 4 - CONN:3952426"
2023-06-27 13:53:42.728 WIB,"dbas","pccwms502Zdb",105829,"172.19.6.187:1032",649a5d9e.19d65,15057,"SELECT",2023-06-27 10:55:10 WIB,43/1567572,840415340,LOG,00000,"duration: 0.019 ms plan:
Query Text: insert into t1(id) select * from t2 where sfc.id=t2.id
Insert on t1 (cost=0.29..4.31 rows=1 width=4) (actual rows=0 loops=1)
-> Index Only Scan using idx_t2_id on t2 (cost=0.29..4.31 rows=1 width=4) (actual rows=1 loops=1)
Index Cond: (id = $4)
Heap Fetches: 0",,,,,"SQL statement ""insert into t1(id) select * from t2 where sfc.id=t2.id""
PL/pgSQL function pro_test1() line 11 at SQL statement",,,,"pgAdmin 4 - CONN:3952426"
2023-06-27 13:53:42.728 WIB,"dbas","pccwms502Zdb",105829,"172.19.6.187:1032",649a5d9e.19d65,15058,"SELECT",2023-06-27 10:55:10 WIB,43/1567572,840415340,LOG,00000,"duration: 0.009 ms plan:
Query Text: insert into t1(id) select * from t2 where sfc.id=t2.id
Insert on t1 (cost=0.29..4.31 rows=1 width=4) (actual rows=0 loops=1)
-> Index Only Scan using idx_t2_id on t2 (cost=0.29..4.31 rows=1 width=4) (actual rows=1 loops=1)
Index Cond: (id = $4)
Heap Fetches: 0",,,,,"SQL statement ""insert into t1(id) select * from t2 where sfc.id=t2.id""
PL/pgSQL function pro_test1() line 11 at SQL statement",,,,"pgAdmin 4 - CONN:3952426"
2023-06-27 13:53:42.728 WIB,"dbas","pccwms502Zdb",105829,"172.19.6.187:1032",649a5d9e.19d65,15059,"SELECT",2023-06-27 10:55:10 WIB,43/1567572,840415340,LOG,00000,"duration: 0.007 ms plan:
Query Text: insert into t1(id) select * from t2 where sfc.id=t2.id
Insert on t1 (cost=0.29..4.31 rows=1 width=4) (actual rows=0 loops=1)
-> Index Only Scan using idx_t2_id on t2 (cost=0.29..4.31 rows=1 width=4) (actual rows=1 loops=1)
Index Cond: (id = $4)
Heap Fetches: 0",,,,,"SQL statement ""insert into t1(id) select * from t2 where sfc.id=t2.id""
PL/pgSQL function pro_test1() line 11 at SQL statement",,,,"pgAdmin 4 - CONN:3952426"
2023-06-27 13:53:42.729 WIB,"dbas","pccwms502Zdb",105829,"172.19.6.187:1032",649a5d9e.19d65,15060,"SELECT",2023-06-27 10:55:10 WIB,43/1567572,840415340,LOG,00000,"duration: 0.010 ms plan:
Query Text: (select id from t2 where id >9997)
Index Only Scan using idx_t2_id on t2 (cost=0.29..4.34 rows=3 width=8) (actual rows=3 loops=1)
Index Cond: (id > 9997)
Heap Fetches: 0",,,,,"PL/pgSQL function pro_test1() line 8 at FOR over SELECT rows",,,,"pgAdmin 4 - CONN:3952426"
2023-06-27 13:53:42.729 WIB,"dbas","pccwms502Zdb",105829,"172.19.6.187:1032",649a5d9e.19d65,15061,"SELECT",2023-06-27 10:55:10 WIB,43/1567572,840415340,LOG,00000,"duration: 1.075 ms plan:
Query Text: select pro_test1()
Result (cost=0.00..0.26 rows=1 width=32) (actual rows=1 loops=1)",,,,,,,,,"pgAdmin 4 - CONN:3952426"
这里,可以看到输出的完整执行计划,甚至每一个for循环的执行计划都有记录下来,这对我们查看复杂sql的执行计划非常的有帮助
set autoexplain.log_min_duration to -1