【问题标题】:EXPLAIN ANALYZE within PL/pgSQL gives error: "query has no destination for result data"PL/pgSQL 中的 EXPLAIN ANALYZE 给出错误:“查询没有结果数据的目的地”
【发布时间】:2014-04-01 19:31:16
【问题描述】:

我正在尝试了解 PL/pgSQL 函数中 select 语句的查询计划,但我不断收到错误消息。我的问题:如何获取查询计划?

以下是重现问题的简单案例。

有问题的表名为 test_table。

CREATE TABLE test_table
(
  name character varying,
  id integer
);

函数如下:

DROP FUNCTION IF EXISTS test_function_1(INTEGER);
CREATE OR REPLACE FUNCTION test_function_1(inId INTEGER) 
RETURNS TABLE(outName varchar)
AS 
$$
BEGIN
  -- is there a way to get the explain analyze output?
  explain analyze select t.name from test_table t where t.id = inId;

  -- return query select t.name from test_table t where t.id = inId;
END;
$$ LANGUAGE plpgsql;

当我跑步时

select * from test_function_1(10);

我得到错误:

ERROR:  query has no destination for result data
CONTEXT:  PL/pgSQL function test_function_1(integer) line 3 at SQL statement

如果我取消注释注释部分并注释掉解释分析,该函数可以正常工作。

【问题讨论】:

    标签: sql postgresql plpgsql explain


    【解决方案1】:

    或者你可以使用RETURN QUERY这个更简单的形式:

    CREATE OR REPLACE FUNCTION f_explain_analyze(int)
      RETURNS SETOF text AS
    $func$
    BEGIN
       RETURN QUERY
       EXPLAIN ANALYZE SELECT * FROM foo WHERE v = $1;
    END
    $func$ LANGUAGE plpgsql;
    

    呼叫:

    SELECT * FROM f_explain_analyze(1);
    

    在 Postgres 9.3 中为我工作。

    【讨论】:

    • 这看起来是一个非常好的解决问题和开发新功能的解决方案。您的函数中可以有多个 RETURN QUERY,如果您的函数有 10 个查询,您可以添加一个 RETURN QUERY EXPLAIN ANALYZE 并为每个查询返回一个解释。不错!
    【解决方案2】:

    任何查询都必须在 plpgsql 中有一个已知的目标(或者您可以使用 PERFORM 语句丢弃结果)。所以你可以这样做:

    CREATE OR REPLACE FUNCTION fx(text)
    RETURNS void AS $$
    DECLARE t text;
    BEGIN
      FOR t IN EXPLAIN ANALYZE SELECT * FROM foo WHERE v = $1
      LOOP
        RAISE NOTICE '%', t;
      END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    
    postgres=# SELECT fx('1'); NOTICE: Seq Scan on foo (cost=0.00..1.18 rows=1 width=3) (实际时间=0.024..0.024 rows=0 loops=1) 注意:过滤器:((v)::text = '1'::text) 注意:过滤器删除的行数:14 注意:规划时间:0.103 ms 注意:总运行时间:0.065 毫秒 外汇 ──── (1 行)

    获得嵌入式 SQL 计划的另一种可能性是使用准备好的语句:

    postgres=# PREPARE xx(text) AS SELECT * FROM foo WHERE v = $1; 准备 时间:0.810 毫秒 postgres=#解释分析执行 xx('1'); 查询计划 ────────────────────────────────────────────────── ──────────────────────────────────────────── Seq Scan on foo (cost=0.00..1.18 rows=1 width=3) (实际时间=0.030..0.030 rows=0 loops=1) 过滤器:((v)::text = '1'::text) 过滤器删除的行数:14 总运行时间:0.083 毫秒 (4 行)

    【讨论】:

      【解决方案3】:

      您可以查看http://www.postgresql.org/docs/current/static/auto-explain.html 并在日志文件中捕获说明。

      还要看看这是否符合您的要求。 https://github.com/pgexperts/explanation

      【讨论】:

      • 这(auto_explain)有效,但在我的案例中比公认的解决方案需要更多的努力。感谢您的回复(不知道您为什么被否决!)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-27
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多