gpt4 book ai didi

PostgreSQL 可变表达式和子查询

转载 作者:行者123 更新时间:2023-11-29 11:29:02 26 4
gpt4 key购买 nike

在 Bruce Momjian 的博文中 Generating Random Data Via SQL他使用以下代码生成了 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 缓存了外部选择表达式(结果)!

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

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

更新:

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

...
SELECT chr(ascii('a') + floor(random() * 26 + b * 0)::integer)
FROM generate_series(1, 40) as s(f)
...

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

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

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)

没有b*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的每一行重新进行评估。

关于PostgreSQL 可变表达式和子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11645087/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com