使用Postgres中的解释分析创建函数来检查执行时间

时间:2019-01-27 10:42:35

标签: postgresql

我运行了一些查询以获取执行时间

输入查询

explain analyze SELECT * FROM employee emp where emp.empid = ' 00010   ';

输出结果

"Seq Scan on employee emp  (cost=0.00..279.00 rows=1 width=90) (actual time=0.014..3.341 rows=1 loops=1)"
"  Filter: (empid = ' 00010   '::bpchar)"
"  Rows Removed by Filter: 9999"
"Planning time: 0.066 ms"
"Execution time: 3.356 ms"

然后我编写了如下函数

CREATE OR REPLACE FUNCTION test19() RETURNS TEXT AS $$
DECLARE total TEXT;
BEGIN
    EXPLAIN ANALYZE into total SELECT * FROM employee emp, payroll pr where emp.empid = ' 00010   ';
    RETURN total;
END;

但是当我运行函数时

输入查询

select * from test19()

输出结果

Nested Loop  (cost=0.00..543.00 rows=10000 width=108) (actual time=0.022..9.311 rows=10000 loops=1)

因此,函数的输出不包含执行时间。我在功能上面犯了什么错误?

3 个答案:

答案 0 :(得分:2)

您可以将EXPLAIN ANALYZE的输出作为XML / JSON返回并进行解析:

CREATE OR REPLACE FUNCTION test19() RETURNS TEXT
AS $$
DECLARE total TEXT;
BEGIN
    EXPLAIN (ANALYZE, TIMING, FORMAT JSON) into total SELECT 1 AS c;
    RETURN ((total::jsonb)-> 0 -> 'Execution Time');
END;
$$  LANGUAGE plpgsql;

db<>fiddle demo

答案 1 :(得分:0)

我创建了以下函数,我不敢相信它能起作用...

CREATE OR REPLACE FUNCTION test19(query TEXT) RETURNS JSON language 'plpgsql' AS $$
DECLARE total JSON;
BEGIN
    EXECUTE 'EXPLAIN (ANALYZE, FORMAT JSON) ' || query into total;
    RETURN total;
END;
$$;

这是一个使用方法的示例(与我的数据库相关的查询,请替换为您自己的查询):

WITH Queries(q) AS (
    VALUES ('SELECT * FROM Price'),
    ('SELECT * FROM Price WHERE PriceTypeIK=2 AND PriceDate > current_date - interval ''50 days''')
)
SELECT q, (test19(q)->0->'Plan'->>'Actual Total Time')::FLOAT from queries;

确保始终在回滚或保存点,回滚到保存点然后提交的事务中使用它。

编辑:最后一条评论,我意识到我没有写过:您不必只提取实际的总时间,因为我已经为其编写了函数以返回整个计划。 (使用上面的方法尝试SELECT q, test19(q) from queries)。

答案 2 :(得分:0)

PL / pgSQL中的

SELECT INTO仅处理一行。

EXPLAIN返回多行,因此您的函数仅返回第一行。

如果只想提取执行时间,则可以解析Lukasz所示的JSON输出,或者需要一个循环:

create or replace function show_time(to_explain text)
  returns text,
as
$$
declare
  l_plan_line record;
  l_line text;
begin
   l_line := 1;
   for l_plan_line in execute 'explain (analyze, verbose, format text)'||to_explain    
   loop
      l_line := l_plan_line."QUERY PLAN"::text;
      if l_line like 'Execution Time%' then 
         return l_line;
      end if;
   end loop;
   return null;
end;
$$
language plpgsql;