Deterministic/Volatile SQL 中的函数

Deterministic/Volatile function in SQL

让我们来看一个基本的确定性函数和一个非确定性函数:

第三种可能会改变但我们不确定的情况呢,例如:

SELECT
    ABS(2) -- deterministic
  , NOW()  -- not
  , getTableCount(otherTbl) -- function that does a 'SELECT count(1) FROM table'
FROM
    table

基本上,如果插入或删除一行,subselect 的值将会改变。那么那个会被认为是确定性的吗?结果应该总是一样的……除非基础数据发生变化,所以它几乎就像第三种情况。或者,volatile/non-deterministic 只是表示“如果它在任何情况下都发生过变化,那么它就是不稳定的。” ?

我将利用我的大学学业,所以在信息学和 philosophy/lingüistics(命题逻辑)中。在这里我们可以去各个方向,但我想留在 Wittgenstein (Wittgenstein I from Tractatus Logicus-Philosophicus)。

由于评论和文档的完整性,我们可以得出结论,从静态观察者的角度来看,附加到静态力的动态力将是动态力。

问题中的例子很好。今天的1和昨天一样吗?好吧,不是。它是不一样的,因为我们不知道它在时间上意味着什么。例如,可以是总数量:我们有多少颗卫星?一。但在数百万年后,将没有月亮,或者根本没有月亮,因为我们已经不在了。或质量:比什么多或少? 1 可以是很多,也可以是少而不是多。

那么如果没有确定性系统(洛伦兹知道),它们之间有什么区别?该值是否会更改。记住这个定义,让我们来看看逻辑:

1n 是否可以在某些 n 值上与 2n 不同?是
1n 是否可以在某个 n 值中等于 2n?是
我们可以知道 1n 总是不同于 2n 吗?是

因此,即使处置的一个元素是确定性的,结果也不是确定性的。

对于 确定性 有不同的解释,即使仅限于 SQL 函数域。这取决于消费者需要和假设的确定性。

确定性的通常定义是确定性函数在其参数的输入参数值相同时总是return相同的值。

如果函数使用状态,它会隐含地将其视为额外的输入参数。原来的function(p1,...pn)会变成function(p1,...pn,state)。但是在这种情况下,如果比较两个不同的状态,那么输入就不会相同,所以我们不能再谈论确定性了。知道这一点,我们将使用术语 state-sensitive-determinismstate-insensitive-determinism 来区分这些情况。

我们的 state-insensitive-determinism 相当于 PostgreSQL 的 IMMUTABLE(PostgreSQL 是一个很好的比较,因为它避免使用术语确定性来避免混淆,因为可以在 postgresql docs 中看到)。在这种情况下,无论状态如何,函数总是 returns 相同的值(示例 select 1+2)。这是最严格的确定性形式,消费者通常认为这是理所当然的——例如,查询优化器可以用它们的结果替换它们(select 1+2 会变成 select 3)。在这些情况下,状态不会影响结果。所以,即使我们把状态作为一个额外的参数,函数的结果仍然是一样的。

当面对相同的状态结果没有改变但有改变的风险时,我们有我们的 state-sensitive-determinism 或 PostgreSQL 的 STABLE(示例 select v,sum(v) over () from tbl where v>1000;)。 确定性这里是灰色地带。查询优化器消费者认为它是确定性的,因为由于查询处于明确定义的状态,至少在可事务数据库中,只计算一次而不是多次计算是很好的,因为未来的计算结果会相同。但是具体化的计算列或索引不能接受这个相同的函数作为确定性函数,因为状态的一点变化都会使其所有预先计算和存储的值变得无效。在这种情况下驻留 OP 的 getTableCount(otherTbl)。对于查询优化器,它的确定性足以避免额外的计算,对于具体化的计算值来说,它是不够的,不能被接受为被写入的价值来源。如果我们使用状态作为额外的参数,结果可能会在不同状态之间发生变化。

如果我们使用的值是基于某些不受控制的状态生成的,例如 random()(至少当我们不选择种子和伪随机函数时),那么我们无法实现确定性。在 PostgreSQL 的术语中,这将是 VOLATILEVOLATILE 本质上是不确定的,因为即使在相同的 table 扫描中它也可以有不同的值,就像 random() 的情况一样(有关时间相关的函数,请参见 Postgres now() timestamp doesn't change, when script works,时间可能是交易时间,也可能是查询时间,这会影响您对确定性的看法。

MySQL有不同的关键字,NOT DETERMINISTICDETERMINISTICREADS SQL DATAMODIFIES SQL DATA(类似于PostgreSQL的LEAKPROOF), NO SQL CONTAINS SQL 如在 mysql docs 上所见,与 PostgreSQL 相同的 objective - 向特定消费者提供提示,无论是查询优化器或物化价值,它是否会根据其对决定论的解释来调整其行为。数据库供应商可能将此责任留给了用户,因为他们有责任确定影响复杂和问题的因果图。

当供应商谈论确定性时,他们可能会谈论我们所说的其中一个。在 sqlserver docs microsoft says that state must be the same, so they are probably talking about our state-sensitive-determinism. In sqlite docs otherwise it is taken the state-insensitive-determinism approach, where functions that must result equally even in different states to be considered deterministic, because they would follow stricter rules. Oracle implicitly follows the same sqlite flavor in their docs.

我们的事务性数据库最终将使用某种机制(如 MVCC)来保存事务中的状态。在这种情况下,我们可以将 transactionTimestamp 视为我们函数的输入。但如果我们采用更复杂的情况,如分布式数据库,那么我们的确定性可能更难实现,最终它必须考虑共识算法。