Postgres功能比Query / Postgres 8.4慢

时间:2016-03-10 10:59:00

标签: sql performance postgresql plpgsql postgresql-8.4

我(必须)使用Postgres 8.4数据库。在这个数据库中我创建了一个函数:

CREATE OR REPLACE FUNCTION counter (mindate timestamptz,maxdate timestamptz) RETURNS integer AS $func$ 
DECLARE result integer; 
BEGIN
Select INTO result COUNT(*) AS counter from columname where starttime BETWEEN $1 and $2;
Return result;  
END
$func$ LANGUAGE plpgsql;

查询:

apptelemetry=# select counter('2016-03-01 00:00:00','2016-03-11 00:00:00');
 requestcounter
----------------
           8893
(1 row)

Time: 4.740 ms

当我进行正常查询时:

apptelemetry=# select Count(*) from columname where starttime BETWEEN '2016-03-01 00:00:00' AND '2016-03-11 00:00:00';
 count
-------
  8893
(1 row)

Time: 3.214 ms

为什么函数比普通查询慢?有人为我提供性能提示吗?

Regrads

2 个答案:

答案 0 :(得分:3)

PL / pgSQL函数具有设置其环境的开销。但是,在您的情况下,您可以使用效率更高的SQL语言函数:

CREATE FUNCTION counter (mindate timestamptz, maxdate timestamptz) RETURNS integer AS
$func$ 
  SELECT count(*) FROM columname WHERE starttime BETWEEN $1 AND $2;
$func$ LANGUAGE sql;

只有当您需要SQL语言不支持的功能时,例如条件分支,才应该使用PL / pgSQL。

也就是说,实际运行时间可能会受到DBMS内部或外部的许多因素的影响,因此单个运行的简单比较可能会受到这些影响的影响。

答案 1 :(得分:2)

PLpgSQL中的查询是盲目优化的。有时,某些参数的执行计划可能不是最理想的。

PLpgSQL重用任何查询的执行计划。它有一些优点(没有重复的昂贵的查询计划),但它也有一些缺点(该计划没有针对实际值进行优化,它针对最可能的值进行了优化)。 Postgres的现代版本有点聪明。

此查询的解决方案是动态SQL。在这种情况下,执行计划不会被重用,然后可以针对实际参数的值进行优化:

CREATE OR REPLACE FUNCTION counter (mindate timestamptz,maxdate timestamptz) RETURNS integer AS $func$ 
DECLARE result integer; 
BEGIN
  EXECUTE 'SELECT COUNT(*) FROM columname 
             WHERE starttime BETWEEN $1 and $2'
     INTO result USING mindate, maxdate;
  RETURN result;  
END
$func$ LANGUAGE plpgsql;

关于此问题的一篇文章:http://blog.endpoint.com/2008/12/why-is-my-function-slow.html