Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL易失性表达式和子查询_Postgresql_Generate Series - Fatal编程技术网

PostgreSQL易失性表达式和子查询

PostgreSQL易失性表达式和子查询,postgresql,generate-series,Postgresql,Generate Series,在Bruce Momjian的博客文章中,他使用以下代码生成了5个随机字符串: SELECT ( SELECT string_agg(x, '') FROM ( SELECT chr(ascii('a') + floor(random() * 26)::integer) FROM generate_series(1, 40 + b * 0) as f(g) ) AS y(x) ) AS

在Bruce Momjian的博客文章中,他使用以下代码生成了5个随机字符串:

SELECT
(
        SELECT string_agg(x, '')
        FROM (
                SELECT chr(ascii('a') + floor(random() * 26)::integer)
                FROM generate_series(1, 40 + b * 0) as f(g)
        ) AS y(x)
) AS result
FROM generate_series(1,5) as a(b);

              result                  
------------------------------------------
 plwfwcgajxdygfissmxqsywcwiqptytjjppgrvgb
 sjaypirhuoynnvqjdgywfsfphuvzqbbilbhakyhf
 ngtabkjfqibwahlicgisijatliuwgbcuiwujgeox
 mqtnyewalettounachwjjzdrvxbbbpzogscexyfi
 dzcstpsvwpefohwkfxmhnlwteyybxejbdltwamsx
(5 rows)
我想知道为什么第6行需要“b*0”。当我删除它时,结果变成了5个完全相似的字符串,这意味着Postgres缓存了外部选择表达式(result)

我找不到表达式缓存在Postgres中是如何工作的。根据random()函数被标记为VOLATILE,所以,我希望依赖于它的任何表达式也是VOLATILE的

表达式缓存在Postgres中是如何工作的?它在任何地方都有记录吗?为什么“b*0”禁用了random()未禁用的缓存

更新:

为了研究这个问题,我将'b*0'移动到floor()调用内部,使其与random()处于相同的位置/级别:

结果仍然没有被缓存;不同的字符串

更新:显示问题的另一个示例

create sequence seq_test;

SELECT (SELECT nextval('seq_test')) FROM generate_series(1,5);

 ?column? 
----------
        1
        1
        1
        1
        1
(5 rows)
嗯,
random()
本身是易变的,因此不会将具有相同字符的字符串重复到末尾

如果查看带有和不带
b*0
的查询计划,您将看到:

使用
b*0

 Function Scan on generate_series a  (cost=0.00..37530.00 rows=1000 width=4)
   SubPlan 1
     ->  Aggregate  (cost=37.51..37.52 rows=1 width=32)
           ->  Function Scan on generate_series  (cost=0.01..25.01 rows=1000 width=0)
 Function Scan on generate_series a  (cost=37.52..47.52 rows=1000 width=0)
   InitPlan 1 (returns $0)
     ->  Aggregate  (cost=37.50..37.51 rows=1 width=32)
           ->  Function Scan on generate_series  (cost=0.00..25.00 rows=1000 width=0)
b*0

 Function Scan on generate_series a  (cost=0.00..37530.00 rows=1000 width=4)
   SubPlan 1
     ->  Aggregate  (cost=37.51..37.52 rows=1 width=32)
           ->  Function Scan on generate_series  (cost=0.01..25.01 rows=1000 width=0)
 Function Scan on generate_series a  (cost=37.52..47.52 rows=1000 width=0)
   InitPlan 1 (returns $0)
     ->  Aggregate  (cost=37.50..37.51 rows=1 width=32)
           ->  Function Scan on generate_series  (cost=0.00..25.00 rows=1000 width=0)

如果PostgreSQL确定内部聚合不依赖于
a
,则将其作为
InitPlan
进行一次计算,并且其中表达式的波动性与否无关。通过引入子查询对
a
的依赖性,即使其成为一个相关子查询,必须对
a

的每一行重新进行求值,因此,规划人员评估了每一行
f
的内部表达式,尽管它不依赖于它(正确,因为它是易变的),但是外部表达式只计算一次,除非它依赖于行!volatile值不应该基于它着色任何结果吗?就像行依赖关系一样。表达式的波动性将停止其内联,但不会影响planner如何安排查询计划,这取决于子选择是否相关。您的意思是,任何子查询都被视为稳定的,除非它依赖于外部查询的行变量!在我看来,它像一只虫子。我希望volatile表达式对任何表达式或子查询都会产生波动病毒效应。InitPlan是一种优化,它不应该改变结果。“稳定”、“易失性”等不是子查询的属性,只是函数和表达式。SQL是描述查询的一种方式,而不是定义查询的执行方式(尽管我承认这是一个薄弱的论点,SQL以泄漏抽象而闻名),谢谢,但我一点也不相信。不管是不是SQL,由于表达式可以包含子查询,我希望波动性会通过子查询传播。至少应该记录当前的行为。