Postgres 函数比查询/Postgres 8.4 慢

Postgres Function Slower than Query / Postgres 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  and ;
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

为什么函数比正常查询慢?有人对我有性能提示吗?

注册

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

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

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

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

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  and '
     INTO result USING mindate, maxdate;
  RETURN result;  
END
$func$ LANGUAGE plpgsql;

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