gpt4 book ai didi

postgresql - 函数在没有 STRICT 修饰符的情况下执行得更快?

转载 作者:行者123 更新时间:2023-11-29 11:25:17 25 4
gpt4 key购买 nike

当一个简单的 SQL 函数声明为 STRICTanswering this question 时,我偶然发现性能下降.

为了演示,我创建了一个函数的两个变体,以升序对数组的两个元素进行排序。

测试设置

包含 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 毫秒。

我做了一些研究,发现了一个有趣的问题。在大多数情况下,声明 SQL 函数 STRICT 会禁用函数内联。更多关于 PostgreSQL Online Journal 的信息或在 pgsql-performance mailing list或在 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

最佳答案

Maybe an overhead from the repeated function call that is streamlined away by inlining the function?

这就是我猜的。你有一个非常简单的表达式。实际的函数调用大概涉及堆栈设置、传递参数等。

下面的测试给出了 5 毫秒的内联运行时间和 50 毫秒的严格运行时间。

BEGIN;

CREATE SCHEMA f;

SET search_path = f;

CREATE FUNCTION f1(int) RETURNS int AS $$SELECT 1$$ LANGUAGE SQL;
CREATE FUNCTION f2(int) RETURNS int AS $$SELECT 1$$ LANGUAGE SQL STRICT;

\timing on
SELECT sum(f1(i)) FROM generate_series(1,10000) i;
SELECT sum(f2(i)) FROM generate_series(1,10000) i;
\timing off

ROLLBACK;

关于postgresql - 函数在没有 STRICT 修饰符的情况下执行得更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8455177/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com