在布魯斯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)
因此,規劃師對每行「f」的內部表達式進行了評估,儘管它不依賴於它(正確,因爲它是易失性的),但外部表達式只會被計算一次,除非它依賴於行!不應該揮發性值基於它的任何結果色調?就像行依賴一樣。 – 2012-07-25 13:14:46
表達式的波動將阻止它被內聯,但不影響計劃者如何安排查詢計劃,這是基於子查詢是否相關。 – araqnid 2012-07-25 15:32:06
您的意思是任何子查詢都被視爲STABLE,除非它依賴於外部查詢的行變量!它看起來像一個bug。我期望volatile表達式對任何表達式或子查詢都有波動病毒效應。 InitPlan是一種優化,它不應該改變結果。 – 2012-07-26 07:19:48