我有一个非常基本的 plpgsql 存储过程,如下所示:
create or replace procedure new_emp_sp (f_name varchar, l_name varchar, age integer, threshold integer)
language plpgsql
as $$
declare
new_emp_count integer;
begin
INSERT INTO employees (id, first_name, last_name, age)
VALUES (nextval('emp_id_seq'),
random_string(10),
random_string(20),
age);
select count(*) into new_emp_count from employees where age > threshold;
update dept_employees set emp_count = new_emp_count where id = 'finance';
end; $$
使用
call
调用此存储过程后,如何获取该过程执行的每个语句的查询计划?
找到了几个类似要求的 StackOverflow 答案,但使用 functions 而不是使用
auto_explain
模块的过程,我按照以下步骤操作,但它不起作用:
已执行
LOAD '$libdir/plugins/auto_explain';
(我正在使用AWS RDS PostgreSQL实例并在本文档中找到此命令)
已执行
SET auto_explain.log_min_duration = 0;
已执行
SET auto_explain.log_analyze = true;
已执行
SET auto_explain.log_nested_statements = true;
但是执行该过程后,我没有看到输出有任何明显的变化。
对于我当前的要求,我无法访问数据库服务器上的任何日志文件,只能通过客户端/以编程方式在服务器上运行命令
您可以将日志消息发送到客户端:
set client_min_messages TO log;
这对于 auto_explain.log_nested_statements 效果很好(无论如何,在
psql
中)。 我一直使用它以避免需要搜索日志文件。
这是获取存储过程/函数的查询计划的唯一方法吗?
有一个不用安装的方法
auto_explain
。 EXPLAIN
命令返回一组 text
,您可以在 PL/pgSQL 代码块中使用它。
PROCEDURE
(或FUNCTION
)显示临时过程,仅在您的会话中可见。参见:
-- create once:
CREATE OR REPLACE PROCEDURE pg_temp.get_plan ()
LANGUAGE plpgsql AS
$proc$
DECLARE
_line text;
BEGIN
FOR _line IN
EXPLAIN ANALYZE
SELECT 1 -- your query here !!!
LOOP
RAISE NOTICE '%', _line;
END LOOP;
END
$proc$;
-- call:
CALL pg_temp.get_plan();
client_min_messages
处于 NOTICE
或更低:
NOTICE: Result (cost=0.00..0.01 rows=1 width=4) (actual time=0.004..0.005 rows=1 loops=1)
NOTICE: Planning Time: 0.045 ms
NOTICE: Execution Time: 0.035 ms
CALL
FUNCTION
如果函数使用
RETURNS SETOF text
(或等效函数)定义,则可以直接返回 EXPLAIN
的结果。参见:
DO
命令中执行匿名代码块而不创建任何对象:
DO
$do$
DECLARE
_line text;
BEGIN
FOR _line IN
EXPLAIN ANALYZE -- more options?
SELECT 1 -- your query here !!!
LOOP
RAISE NOTICE '%', _line;
END LOOP;
END
$do$
参见: