PostgreSQL的concat_ws函数为何未被标记为immutable?
PostgreSQL的concat_ws函数为何未被标记为immutable?
这个问题我之前做项目优化时也琢磨过,明明现在concat_ws()只接受character、character varying和text这类字符相关类型了,为啥还是没把它标记成IMMUTABLE呢?
先给你捋捋来龙去脉:
- 早版本的PostgreSQL里,
concat_ws()允许传入非字符类型的参数,会自动做隐式类型转换。这时候它肯定不能标IMMUTABLE——比如你传个日期类型,转换后的字符串结果完全依赖数据库的lc_time配置,换个环境跑结果就变了,这种函数当然不能被认为是“永远不变”的。 - 后来版本更新后,官方把
concat_ws()的参数限制成了仅字符类类型,按道理说纯字符拼接的逻辑应该是固定的,输入相同就一定输出相同,这时候改成IMMUTABLE才合理对吧?
但为啥没改呢?核心原因还是向后兼容性。PostgreSQL团队对兼容性的重视程度很高,要是突然把concat_ws()的 volatility 等级从STABLE改成IMMUTABLE,可能会触发一些意想不到的问题:
- 有些老系统里可能还残留着依赖旧版
concat_ws()行为的代码,虽然现在跑会报错,但系统升级时的兼容性检查逻辑可能会受影响; - 数据库的查询优化器对
STABLE和IMMUTABLE函数的处理逻辑不一样,突然变更等级可能导致一些老查询的执行计划出错,引发性能问题或者结果异常。
也正因为它还是STABLE等级,所以你没法把它用在生成列里——毕竟生成列要求表达式必须是IMMUTABLE的,这样数据库才能保证每次读取生成列的值都是固定的,不会因为任何环境或配置变化而改变。
内容来源于stack exchange
相关产品推荐
相关产品推荐

