Erw*_*ter 9 postgresql performance functions
Postgres 函数声明为波动性分类VOLATILE,STABLE或IMMUTABLE。众所周知,该项目对内置函数的这些标签非常严格。并且有充分的理由。突出的例子:表达式索引只允许IMMUTABLE函数并且那些必须是真正不可变的以避免错误的结果。
用户定义的函数仍然可以按照所有者的选择自由声明。手册建议:
为了获得最佳优化结果,您应该使用对它们有效的最严格的波动率类别来标记您的函数。
...并添加了大量可能因波动率标签不正确而出错的事情列表。
尽管如此,在某些情况下,伪造不变性是有道理的。大多数情况下,当您知道该函数实际上在您的范围内是不可变的。例子:
除了对数据完整性的所有可能影响之外,对性能的影响是什么?人们可能认为声明一个函数IMMUTABLE只会对性能有益。是这样吗?
声明函数波动性会IMMUTABLE 损害性能吗?
让我们假设当前的 Postgres 10 来缩小范围,但所有最近的版本都很有趣。
是的,它会损害性能。
可以在调用查询中“内联”简单的 SQL 函数。引用 Postgres Wiki:
LANGUAGE SQL在某些条件下,SQL 函数(即)会将它们的函数体内联到调用查询中,而不是直接调用。这可以带来显着的性能优势, 因为函数体会暴露给调用查询的规划器,后者可以应用诸如常量折叠、质量下推等优化。
大胆强调我的。
为了确保正确性,有许多先决条件。其中之一:
如果函数已声明
IMMUTABLE,则表达式不得调用任何非不可变函数或运算符
这意味着,使用任何非不可变函数但仍被声明的 SQL 函数IMMTUTABLE被排除在此优化之外。由关于 SO 的这些相关答案触发,我一直在进行广泛的测试:
基本上比较简单 SQL 函数的这两个变体(将日期映射到integer,忽略与目的无关的年份):
CREATE FUNCTION f_mmdd_tc_s(date) RETURNS int LANGUAGE sql STABLE AS
$$SELECT to_char($1, 'MMDD')::int$$;
CREATE FUNCTION f_mmdd_tc_i(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT to_char($1, 'MMDD')::int$$; -- cannot be inlined!Run Code Online (Sandbox Code Playgroud)
Postgres 函数to_char()只是STABLE,不是IMMUTABLE(它的所有重载实例 -原因超出了本答案的范围)。所以第二个是假的IMMUTABLE,结果在一个简单的测试中慢了5 倍:
db<>在这里摆弄
这个特定的例子可以替换为等效的:
CREATE FUNCTION f_mmdd(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT (EXTRACT(month FROM $1) * 100 + EXTRACT(day FROM $1))::int$$;
Run Code Online (Sandbox Code Playgroud)
就好像有两个函数调用和更多的计算更加昂贵。但是IMMUTABLE标签是真实的(另外,使用的函数速度更快,强制text转换integer也更昂贵)。
比上述较快变体快 2倍(比较慢变体快 10 倍)。关键是:在可能的情况下使用IMMUTABLE函数,然后您就不必“作弊”一开始。
| 归档时间: |
|
| 查看次数: |
1540 次 |
| 最近记录: |