获取 PostgreSQL 存储过程中语句的查询计划

问题描述 投票:0回答:2

我有一个非常基本的 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
模块的过程,我按照以下步骤操作,但它不起作用:

  1. 已执行

    LOAD '$libdir/plugins/auto_explain';
    (我正在使用AWS RDS PostgreSQL实例并在本文档中找到此命令)

  2. 已执行

    SET auto_explain.log_min_duration = 0;

  3. 已执行

    SET auto_explain.log_analyze  = true;

  4. 已执行

    SET auto_explain.log_nested_statements = true;

但是执行该过程后,我没有看到输出有任何明显的变化。

对于我当前的要求,我无法访问数据库服务器上的任何日志文件,只能通过客户端/以编程方式在服务器上运行命令

postgresql amazon-rds plpgsql
2个回答
3
投票

您可以将日志消息发送到客户端:

set client_min_messages TO log;

这对于 auto_explain.log_nested_statements 效果很好(无论如何,在

psql
中)。 我一直使用它以避免需要搜索日志文件。


2
投票

这是获取存储过程/函数的查询计划的唯一方法吗?

有一个不用安装的方法

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$

参见:

© www.soinside.com 2019 - 2024. All rights reserved.