加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

PostgreSQL易失性表达式和子查询

发布时间:2020-12-13 18:06:19 所属栏目:百科 来源:网络整理
导读:在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)
在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的每一行重新进行评估.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读