Pavel 在如何修复函数方面是 100% 正确的,但基于函数代码,并且因为您使用的是 Greenplum,我猜您想针对大表选择此内联。这样做时,您需要避免 PL/pgSQL 的开销。它是一门很棒的语言,我经常使用它,但我会避免将它用于内联 SQL。使用 PL/pgSQL 封装转换逻辑,而不是内联 SQL。
其次,我会将函数设为 IMMUTABLE,因为您没有在函数中更新数据库,并且对于给定的参数总是返回相同的值。更多关于这里:
http://www.postgresql.org/docs/8.2/static/xfunc-volatility.html
证明:
CREATE OR REPLACE FUNCTION abstime(timeval INTERVAL)
RETURNS INTERVAL AS $$
BEGIN
IF timeval < INTERVAL '00:00:00' THEN
RETURN timeval + INTERVAL '24:00:00';
ELSE
RETURN timeval;
END IF;
END;
$$ LANGUAGE plpgsql;
现在得到解释计划。
EXPLAIN ANALYZE SELECT abstime('04:00:00'::interval);
Result (cost=0.01..0.02 rows=1 width=0)
Rows out: 1 rows with 5.230 ms to end, start offset by 0.124 ms.
InitPlan
-> Result (cost=0.00..0.01 rows=1 width=0)
Rows out: 1 rows with 5.146 ms to end of 2 scans, start offset by 0.130 ms.
Slice statistics:
(slice0) Executor memory: 63K bytes.
(slice1) Executor memory: 37K bytes.
Statement statistics:
Memory used: 128000K bytes
Settings: optimizer=on
Optimizer status: legacy query optimizer
Total runtime: 5.356 ms
现在,将此函数重写为 SQL 函数并使用 IMMUTABLE 标志。
CREATE OR REPLACE FUNCTION abstime_v2(timeval INTERVAL)
RETURNS INTERVAL AS
$$
SELECT CASE WHEN $1 < INTERVAL '00:00:00' THEN $1 + INTERVAL '24:00:00' ELSE $1 END;
$$
LANGUAGE sql IMMUTABLE;
解释计划。
EXPLAIN ANALYZE SELECT abstime_v2('04:00:00'::interval);
Result (cost=0.00..0.00 rows=1 width=16)
Rows out: 1 rows with 0.002 ms to end, start offset by 0.042 ms.
-> Result (cost=0.00..0.00 rows=1 width=1)
Rows out: 1 rows with 0.001 ms to end, start offset by 0.043 ms.
Slice statistics:
(slice0) Executor memory: 13K bytes.
Statement statistics:
Memory used: 128000K bytes
Settings: optimizer=on
Optimizer status: PQO version 1.607
Total runtime: 0.046 ms
v2 功能所需的扫描和内存更少。