2012-07-25 2 views
5

Generating Random Data Via SQL 그는 5 임의의 문자열을 생성하기 위해 다음 코드를 사용했다. 제가 제거했을 때, 결과는 정확하게 비슷한 문자열로 변경되었습니다. 즉, Postgres가 외부 선택 식 (결과)을 캐시했음을 의미합니다!PostgreSQL의 휘발성 표현과 하위 쿼리 브루스 Momjian의 블로그 게시물에서

어떻게 표현 캐싱이 Postgres에서 작동하는지 찾을 수 없습니다. the documentation에 따르면 random() 함수는 VOLATILE로 표시되어 있으므로 모든 표현이 너무 휘발성 일 것으로 예상됩니다.

어떻게 표현 캐싱이 Postgres에서 작동합니까? 어디에서 문서화되어 있습니까? 왜 'b * 0'이 random()이없는 캐시를 비활성화 했습니까?

는 업데이트 :

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

그 결과

문제를 연구하기 위해, I()는 (동일한 위치/레벨에서 무작위로 호출) 바닥의 내부에 'B * 0'이동 여전히 캐시되지 않습니다. 다른 문자열.

업데이트 : 또 다른 예는 따라서 당신이 마지막에 반복 같은 문자로 문자열을 얻을하지 않습니다 자체가 휘발성 문제를

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에 종속되지 않으며 한 번으로 평가됩니다., 그리고 내부의 표현의 변동성은 부적합합니다. 하위 쿼리의 종속성을 a에 도입하여 즉, 상관 된 하위 쿼리로 만들면 a의 각 행에 대한 평가를 다시 수행해야합니다.

+0

따라서 플래너는 각 행'f'에 종속되지는 않지만 (올바르게 휘발성이기 때문에) 각 행에 대한 내부 표현식을 평가하지만 행에 종속적이지 않으면 외부 표현식이 한 번 평가됩니다! 휘발성 값은 그 값에 기초하여 어떤 결과도 색칠하지 않아야합니까? 행 종속성과 마찬가지로. –

+0

표현식의 변동성으로 인해 인라인 될 수 없지만 plseanner가 subselect와 상관 관계가 있는지 여부에 따라 쿼리 계획을 정렬하는 방식에는 영향을 미치지 않습니다. – araqnid

+0

하위 쿼리는 외부 쿼리의 행 변수에 의존하지 않는 한 STABLE로 간주됩니다. 그것은 나에게 버그처럼 보인다. 휘발성 표현식이 표현식이나 하위 쿼리에 변동성 바이러스 효과가있을 것으로 기대합니다. InitPlan은 최적화이므로 결과를 변경해서는 안됩니다. –