PostgreSQL:不可变,易变,稳定


11

我不清楚IMMUTABLE,VOLATILE和STABLE函数的定义的真正含义。

我阅读了文档,特别是每个文档的定义。

IMMUTABLE指示该函数无法修改数据库,并且 在给定相同的参数值时始终返回相同的结果;也就是说,它不执行数据库查找或以其他方式使用其参数列表中不直接存在的信息。如果指定了此选项,则可以使用函数值立即替换具有全常数参数的任何函数调用。

STABLE表示该函数无法修改数据库,并且在单个表扫描中它将针对相同的参数值一致地返回相同的结果,但其结果可能会在SQL语句之间发生变化。对于其结果取决于数据库查找,参数变量(例如当前时区)等的函数,这是适当的选择。(对于希望查询当前命令修改的行的AFTER触发器来说,这是不合适的。)还请注意, current_timestamp系列功能符合稳定条件,因为它们的值在事务中不会更改。

VOLATILE表示该功能值即使在一次表扫描中也可以更改,因此无法进行优化。从这个意义上说,相对来说很少有数据库函数是易变的。一些示例是random(),currval(),timeofday()。但是请注意,任何具有副作用的函数都必须归类为易失性,即使其结果是可以预测的,也可以防止调用被优化。一个示例是setval()。

我的困惑来自与不可改变的条件,稳定的功能总是始终返回相同的结果给出了相同的论点。

IMMUTABLE定义指出该函数不进行数据库查找或以其他方式使用未直接存在于其参数列表中的信息。因此,对我而言,这意味着此类函数用于操作客户端提供的数据,并且不应具有SELECT语句……尽管这听起来有点奇怪。

使用STABLE时,定义是相似的,因为它表示应始终返回相同的结果。因此,对我来说,这意味着每次使用相同的参数调用该函数时,它应返回相同的结果(相同的行,每次相同)。

因此,对我来说...意味着对表或可更新表执行SELECT的任何函数都应仅是易失性的。

但是,再次...对我来说听起来不对。

回到我的用例,我正在编写函数,这些函数在不断添加的表上执行带有多个JOIN的SELECT语句,因此,即使每次调用时,即使使用相同的参数,也希望函数调用返回不同的结果。 。

那么,这是否意味着我的功能应该是挥发性的?即使文档表明在这种意义上相对较少的数据库功能也是易失的

谢谢!

Answers:


15

IMMUTABLE必须是纯函数,其结果取决于其输入。这是一个非常严格的要求;他们不能调用其他不可更改的函数,不能访问表,不能访问配置属性的值,等等。

STABLE可以使用任何本身就是STABLE其他STABLEIMMUTABLE函数的输入以及SELECT对表的查询。查询表是安全的,因为这些表的函数视图在查询的当前快照中不会更改。您可以访问GUC值(current_setting(...)),只要您知道它们也不会在当前语句中分配给它们即可。

VOLATILE 函数是不符合以上条件的所有内容:

  • 任何有副作用的东西
  • 确实写的任何东西
  • 任何查询不受PostgreSQL快照管理的外部数据的内容
  • ...

通常,VOLATILE除非您有充分的理由不这样做,否则就随便丢掉所有东西。

使用的主要原因IMMUTABLE是在编写要用作索引表达式一部分的函数时。


1
“他们无法访问表。” 公平地说,他们可以并且可以做到。我认为,更普遍的规则是,如果不重新启动数据库,就不应对表进行有意义的更改。
埃文·卡洛尔

如果STABLE允许表访问,是否在VOLATILE之上/之上有任何优化...?
布鲁克斯

不记得我的头顶了,将不得不检查文档/代码。
Craig Ringer

4

对于STABLE,您需要加粗的部分是“结果可能会在SQL语句中发生变化”

不宜改变的事情永远都不会改变。即使您重新启动数据库服务器,运行yum update(当然可以有虫子!),更改配置(如datestyletimezonedefault_text_search_configextra_float_digits,等),或完全替代服务器硬件(相同的架构旧硬件的,所以二进制文件仍然兼容)。

您所描述的功能听起来像是稳定的,因为在单个SQL语句中,它们将使用与外部查询相同的快照执行查询,因此对这些其他表所做的任何并发更改都将不可见。现在,如果您的函数打开了与服务器的新连接并在该独立连接中运行查询,则将使函数易失,因为它们将使用不同的快照。


我相信我了解IMMUTABLE(在查询,连接,重新启动,行星破坏和重建之间,即使在数据库被修改的情况下,一切都无法改变...。)和VOLATILE(该函数在被称为)。那是对的吗?因此,看起来STABLE只是意味着该函数不会修改数据库并且不会在其上下文之外访问数据库?STABLE的定义感觉比实际需要的要复杂得多……还是我遗漏了一些东西?
Brooks

PostgreSQL实际上存在一些问题IMMUTABLE和排序规则。它相信glibc(或在较新的Pg中,iconv)不会更改排序规则定义。实际上,它们确实存在,并且没有提供检测此类变化的方法。它可以导致沉默指数腐败:(这主要是一个问题,不同的操作系统版本之间进行复制,等时。
克雷格·林格
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.