在 Spanner 中,函数(包括内置 SQL 函数和用户定义的函数)按其易变性进行分类。易变性类别表示当您使用相同的实参调用函数时,该函数是否返回相同的结果。此分类会影响查询优化器处理函数的方式以及您可以在何处使用该函数,例如在生成列表达式或索引定义中。了解函数易变性有助于您在 Spanner 中编写更可预测且性能更高的查询和架构。
共有三个易变性类别,它们与 PostgreSQL等系统中的概念类似:
不可变:如果使用相同的实参值调用函数时,该函数返回相同的结果,则该函数是不可变的。此行为意味着函数的结果仅取决于其输入实参,而不取决于数据库状态、会话设置或外部因素。大多数数学函数都是不可变的。以下函数是示例:
依赖于运行时可配置设置(例如 time zone)的函数不是不可变的,因为它们的结果可能会因不同的数据库或 会话配置而异。
稳定:如果函数在单个语句执行中针对 相同的实参值返回相同的结果,则该函数是稳定的。不过,其结果可能会因不同的 SQL 语句而异。`CURRENT_TIMESTAMP`
CURRENT_TIMESTAMP、`CURRENT_DATE`CURRENT_DATE和类似基于时间的函数都是稳定的。例如,在同一SELECT语句中多次调用CURRENT_TIMESTAMP会产生相同的时间戳,但后续语句可能会产生不同的时间戳。易变:如果函数的值即使在 单个语句执行中针对相同的实参也会发生变化,则该函数是易变的。例如,
GENERATE_UUID函数(用于生成唯一 ID)是易变的。
易变性影响
函数的易变性类别决定了它可以在数据库架构中使用哪些位置,以及如何优化包含该函数的查询:
生成列: 定义 生成列的表达式必须是 不可变的。这可确保存储的值是根据行中的其他列确定的。如果您尝试使用不可变的表达式定义生成列,Spanner 会生成错误。
索引: 您无法针对涉及易变函数的表达式创建索引。如果您尝试针对涉及易变函数的表达式创建索引,Spanner 会生成错误。
查询优化: 查询优化器使用易变性信息来执行优化。例如, 查询优化器会预先计算 使用常量实参调用不可变函数的调用。优化器通常会在单个语句执行范围内缓存稳定函数的结果。