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