2012-07-25 28 views
5

在布魯斯Momjian的博客文章Generating Random Data Via SQL他用下面的代碼生成5個隨機字符串:PostgreSQL的揮發性表達式和子查詢

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' 到地板內()調用​​是在相同的位置/水平爲隨機():

... 
       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) 

回答

4

好,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重新進行評估。

+0

因此,規劃師對每行「f」的內部表達式進行了評估,儘管它不依賴於它(正確,因爲它是易失性的),但外部表達式只會被計算一次,除非它依賴於行!不應該揮發性值基於它的任何結果色調?就像行依賴一樣。 – 2012-07-25 13:14:46

+0

表達式的波動將阻止它被內聯,但不影響計劃者如何安排查詢計劃,這是基於子查詢是否相關。 – araqnid 2012-07-25 15:32:06

+0

您的意思是任何子查詢都被視爲STABLE,除非它依賴於外部查詢的行變量!它看起來像一個bug。我期望volatile表達式對任何表達式或子查詢都有波動病毒效應。 InitPlan是一種優化,它不應該改變結果。 – 2012-07-26 07:19:48