STRICT
当我在回答这个问题时声明了一个简单的 SQL 函数时,我偶然发现了性能下降。
为了演示,我创建了一个函数的两个变体,按升序对数组的两个元素进行排序。
测试设置
包含 10000 个随机整数对的表 (
CREATE TABLE tbl (arr int[]);
INSERT INTO tbl
SELECT ARRAY[(random() * 1000)::int, (random() * 1000)::int]
FROM generate_series(1,10000);
STRICT
没有修饰符的函数:
CREATE OR REPLACE FUNCTION f_sort_array(int[])
RETURNS int[]
LANGUAGE sql IMMUTABLE AS
$func$
SELECT CASE WHEN $1[1] > $1[2] THEN ARRAY[$1[2], $1[1]] ELSE $1 END;
$func$;
带修饰符的函数STRICT
(其他相同):
CREATE OR REPLACE FUNCTION f_sort_array_strict(int[])
RETURNS int[]
LANGUAGE sql IMMUTABLE STRICT AS
$func$
SELECT CASE WHEN $1[1] > $1[2] THEN ARRAY[$1[2], $1[1]] ELSE $1 END;
$func$;
结果
我执行了大约 20 次,并从EXPLAIN ANALYZE
.
SELECT f_sort_array(arr) FROM tbl; -- Total runtime: 43 ms
SELECT f_sort_array_strict(arr) FROM tbl; -- Total runtime: 103 ms
这些是 Debian Squeeze 上 Postgres 9.0.5 的结果。8.4 上的类似结果。
在所有 NULL 值的测试中,两个函数执行相同:~37 ms。
我做了一些研究,发现了一个有趣的问题。在大多数情况下,声明 SQL 函数STRICT 会禁用函数内联。更多关于PostgreSQL Online Journal或pgsql-performance 邮件列表或Postgres Wiki的信息。
但我不太确定这怎么可能是解释。在这个简单的场景中,不内联函数会导致性能下降?没有索引,没有光盘读取,没有排序。也许通过内联函数简化了重复函数调用的开销?
重新测试
同样的测试,同样的硬件,Postgres 9.1。更大的差异:
SELECT f_sort_array(arr) FROM tbl; -- Total runtime: 27 ms
SELECT f_sort_array_strict(arr) FROM tbl; -- Total runtime: 107 ms
相同的测试,新硬件,Postgres 9.6。差距更大,然而:
SELECT f_sort_array(arr) FROM tbl; -- Total runtime: 10 ms
SELECT f_sort_array_strict(arr) FROM tbl; -- Total runtime: 60 ms