我(必须)使用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
答案 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