Postgres 函数使用波动率分类声明VOLATILE
,STABLE
或IMMUTABLE
。众所周知,该项目对内置功能的这些标签非常严格。并且有充分的理由。突出的例子:表达式索引只允许IMMUTABLE
函数,并且那些必须是真正不可变的以避免不正确的结果。
用户定义的函数仍然可以根据所有者的选择自由声明。该手册建议:
为了获得最佳优化结果,您应该使用对其有效的最严格的波动率类别来标记您的函数。
...并添加了一个广泛的列表,其中列出了不正确的波动率标签可能会出错的事情。
不过,在某些情况下,假装不变性是有道理的。大多数情况下,当您知道该函数实际上在您的范围内是不可变的时。例子:
除了对数据完整性的所有可能影响之外,对性能有什么影响?有人可能会认为声明一个函数IMMUTABLE
只会对性能有益。是这样吗?
声明函数波动性IMMUTABLE
会损害性能吗?
让我们假设当前的 Postgres 10 可以缩小范围,但所有最近的版本都值得关注。
是的,它会损害性能。
简单的 SQL 函数可以在调用查询中“内联” 。引用 Postgres Wiki:
大胆强调我的。
为了强制执行正确性,有许多先决条件。其中之一:
这意味着,使用任何非不可变函数但仍被声明的 SQL 函数
IMMTUTABLE
被排除在此优化之外。由这些关于 SO 的相关答案触发,我一直在运行广泛的测试:基本上比较简单 SQL 函数的这两个变体(将日期映射到
integer
,忽略与目的无关的年份):Postgres 函数
to_char()
只是STABLE
,不是IMMUTABLE
(它的所有重载实例——原因超出了这个答案的范围)。所以第二个是假IMMUTABLE
的,在一个简单的测试中结果是慢了 5 倍:db<>在这里摆弄
此特定示例可以替换为等效示例:
使用两个函数调用和更多计算似乎会更昂贵。但是
IMMUTABLE
标签是正确的(另外,使用的功能更快,强制text
执行integer
也更昂贵)。是上述较快变体的2倍(是较慢变体的 10 倍)。关键是:尽可能使用
IMMUTABLE
函数,那么你就不必“作弊”一开始。