作者
digoal
日期
2020-11-20
标签
PostgreSQL , 函数稳定性 , immutable , stable , volatile
背景
PostgreSQL 提供3种函数稳定性, 在执行过程中略有不同:
- immutable, 入参不变, 结果永远不变. 在生成执行计划前被执行, 所以你看执行计划会发现immutable的函数已经被执行了, 所以它在整个运行过程中运算一次. 可用于表达式索引.
- stable, 入参不变, 结果在一个事务中保证不变. 在sql语句开始时执行, 只调用一次. 不可用于索引表达式, 但是可被优化器用于索引条件过滤, where x = stable_func, 可以走索引.
- volatile, 结果随时变化. 不可用于索引表达式, 也不可用于索引过滤. 所以需要逐条执行.
例如下面的例子, 感觉很奇怪, 其实不奇怪
```
postgres=> create table a (id int);
CREATE TABLE
postgres=> insert into a select generate_series(1,1000);
INSERT 0 1000
postgres=> select * from a where id=round(random()*100);
id
28
(1 row)
postgres=> select * from a where id=round(random()*1000);
id
355
440
(2 rows)
```
为什么id=round(random()\*1000); 返回多行? 原因是random()是volatile函数, 逐条执行, 所以有可能出现多次冲撞到相等值, 也有可能没有结果返回, 也可能返回一个, 都在预期内.
List of functions
Schema | Name | Result data type | Argument data types | Type | Volatility | Parallel | Owner | Security | Access privileges | Language | Source code | Description
------------+--------+------------------+---------------------+------+------------+------------+------------+----------+-------------------+----------+-------------+--------------
pg_catalog | random | double precision | | func | volatile | restricted | pg36694487 | invoker | | internal | drandom | random value
(1 row)
当然以上约束只是概念上的, 如果你自定义的函数, 可以实际情况与定义不符, 那么优化器会傻掉, 那是优化器的错吗? 不是, 是你的错, 胡乱定义.
《函数稳定性讲解 - retalk PostgreSQL function's [ volatile|stable|immutable ]》
PostgreSQL 许愿链接
您的愿望将传达给PG kernel hacker、数据库厂商等, 帮助提高数据库产品质量和功能, 说不定下一个PG版本就有您提出的功能点. 针对非常好的提议,奖励限量版PG文化衫、纪念品、贴纸、PG热门书籍等,奖品丰富,快来许愿。开不开森.
9.9元购买3个月阿里云RDS PostgreSQL实例
PostgreSQL 解决方案集合
德哥 / digoal's github - 公益是一辈子的事.





