2012-07-25 27 views
5

Generating Random Data Via SQL彼は5つのランダムな文字列を生成するには、次のコードを使用していました。私が削除したとき、結果はまったく同じ5つの文字列に変更されました。つまり、Postgresは外側のselect式(結果)をキャッシュしました!PostgreSQLの揮発性表現やサブクエリブルースMomjianのブログ記事で

私は式キャッシングが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に依存せず、として1回評価されますであり、その内の式のボラティリティまたは不一致は無関係である。サブクエリの依存性をaに導入すること、すなわちそれを相関サブクエリにすることにより、各行の評価をaに戻す必要があります。

+0

したがって、プランナは、それが依存していなくても(正確には揮発性であるにもかかわらず)各行 'f'の内部式を評価しますが、外側の式は行に依存しない限り1回評価されます。揮発性の値は、それに基づいて何らかの結果をもたらすべきではありませんか?行の依存性と同じように。 –

+0

式のボラティリティにより、インライン化は中止されますが、サブセレクトが相関関係にあるかどうかに基づいてプランナがクエリプランをどのように配置するかには影響しません。 – araqnid

+0

外部クエリの行変数に依存しない限り、サブクエリはSTABLEとみなされます。それは私のバグのように見えます。私は、揮発性の表現が任意の式やサブクエリに対してボラティリティのウイルス効果を持つことを期待します。 InitPlanは最適化であり、結果を変更すべきではありません。 –

関連する問題