PostgreSQL : 불변, 휘발성, 안정적인


11

IMMUTABLE, VOLATILE 및 STABLE 함수의 정의에서 진정한 의미에 대해 잘 모르겠습니다.

설명서, 특히 각각의 정의를 읽었습니다.

IMMUTABLE은 함수가 데이터베이스를 수정할 수 없으며 동일한 인수 값이 제공 될 때 항상 동일한 결과를 리턴 함을 나타냅니다 . 즉, 데이터베이스 조회를 수행하지 않거나 인수 목록에 직접 존재하지 않는 정보를 사용하지 않습니다. 이 옵션을 지정하면 모든 상수 인수가있는 함수 호출을 즉시 함수 값으로 바꿀 수 있습니다.

STABLE은 함수가 데이터베이스를 수정할 수 없으며 단일 테이블 스캔 에서 동일한 인수 값에 대해 동일한 결과를 일관되게 리턴 하지만 결과는 SQL 문에서 변경 될 수 있음을 나타냅니다. 이는 데이터베이스 조회, 매개 변수 (예 : 현재 시간대) 등에 따라 결과가 달라지는 함수에 적합한 선택입니다. (현재 명령으로 수정 된 행을 쿼리하려는 AFTER 트리거에는 적합하지 않습니다.) current_timestamp 함수 계열은 트랜잭션 내에서 값이 변경되지 않으므로 안정적인 것으로 간주됩니다.

VOLATILE은 단일 테이블 스캔에서도 함수 값이 변경 될 수 있으므로 최적화를 수행 할 수 없음을 나타냅니다. 이러한 의미에서 일시적인 데이터베이스 기능은 상대적으로 적습니다. 일부 예는 random (), currval (), timeofday ()입니다. 그러나 부작용이있는 기능은 결과가 상당히 예측 가능하더라도 호출이 최적화되지 않도록 휘발성으로 분류되어야합니다. 예는 setval ()입니다.

내 혼란은 불변에 대한 조건과 기능이 있음을 STABLE에 온다 항상 또는 지속적으로 같은 인수 주어진 동일한 결과를 반환합니다.

IMMUTABLE 정의는 함수가 데이터베이스 검색을 수행하지 않거나 인수 목록에 직접 존재하지 않는 정보를 사용함을 나타냅니다. 따라서 나에게 이것은 그러한 함수가 클라이언트가 제공 한 데이터를 조작하는 데 사용되며 SELECT 문이 없어야한다는 것을 의미합니다 ...하지만 조금 이상하게 들립니다.

STABLE을 사용하면 동일한 결과를 일관되게 반환해야한다는 정의가 비슷합니다. 즉, 함수가 동일한 인수로 호출 될 때마다 동일한 결과 (동일한 정확한 행, 매번)를 반환해야합니다.

따라서 나에게 ... 즉, 업데이트 할 수있는 테이블에서 SELECT를 수행하는 모든 함수는 일시적이어야합니다.

그러나 다시 ... 그게 나에게 들리지 않습니다.

이것을 다시 유스 케이스로 가져 오면 지속적으로 추가되는 테이블에서 여러 개의 JOIN이있는 SELECT 문을 수행하는 함수를 작성하므로 함수 호출은 동일한 인수로도 호출 될 때마다 다른 결과를 반환해야합니다 .

내 기능이 VOLATILE이어야한다는 것을 의미합니까? 비록 문서 가 이런 의미에서 휘발성이 적은 데이터베이스 기능을 거의 나타내지 않더라도 ?

감사합니다!

답변:


15

IMMUTABLE결과 는 입력 에만 의존하는 순수한 함수 여야합니다 . 이것은 매우 엄격한 요구 사항입니다. 변경 불가능한 다른 함수를 호출 할 수 없으며 테이블에 액세스 할 수 없으며 구성 특성의 값에 액세스 할 수 없습니다.

STABLE다른 입력 이나 함수, 테이블 쿼리 STABLE등 모든 입력을 사용할 수 있습니다 . 해당 테이블에 대한 함수의 뷰는 쿼리의 현재 스냅 샷 내에서 변경되지 않으므로 테이블을 쿼리하는 것이 안전합니다. GUC 값 ( )은 현재 명령문 내에서 지정되지 않는 한 액세스 할 수 있습니다 .STABLEIMMUTABLESELECTcurrent_setting(...)

VOLATILE 함수는 위와 맞지 않는 모든 것입니다.

  • 부작용이있는 것
  • 쓰는 모든 것
  • PostgreSQL 스냅 샷에서 관리하지 않는 외부 데이터를 쿼리하는 모든 것
  • ...

일반적으로 VOLATILE정당한 이유가없는 한 모든 것을 그대로 두십시오 .

사용하는 주된 이유 IMMUTABLE는 인덱스 표현식의 일부로 사용될 함수를 작성할 때입니다.


1
"테이블에 액세스 할 수 없습니다." 공정하게, 그들은 할 수 있고 할 수 있습니다. 더 일반적인 규칙은 데이터베이스를 다시 시작하지 않고 테이블을 의미있게 변경해서는 안된다는 것입니다.
Evan Carroll

STABLE이 테이블 액세스를 허용하는 경우 VOLATILE ...에 대한 최적화가 있습니까?
Brooks

내 머리 꼭대기를 기억하지 마십시오. 문서 / 코드를 확인해야합니다.
Craig Ringer

4

STABLE의 경우 굵게 표시해야하는 부분은 '결과가 SQL 문에 따라 변경 될 수 있습니다'입니다.

불명예스러운 일은 결코 바뀌지 않아야합니다. 다시 시작하더라도 데이터베이스 서버는 실행은 yum update(그러나 물론 버그가있을 수 있습니다!), 구성 (같은 변경 datestyle, timezone, default_text_search_config, extra_float_digits그래서 등), 또는 기존의 하드웨어와 동일한 아키텍처 (전체 서버 하드웨어를 교체 바이너리 파일은 여전히 ​​호환됩니다).

단일 SQL 문 내에서 외부 쿼리와 동일한 스냅 샷을 사용하여 쿼리를 실행하므로 다른 테이블에 대한 동시 변경 사항은 표시되지 않으므로 설명하는 함수는 안정적입니다. 이제 함수가 서버에 대한 새로운 연결을 열고 해당 독립 연결 내에서 쿼리를 실행하면 다른 스냅 샷을 사용하기 때문에 함수가 일시적으로 변합니다.


나는 IMMUTABLE의 전제 조건 (데이터베이스가 수정 된 경우에도 쿼리, 연결, 재부팅, 유성 파괴 및 재구성, 심지어 데이터베이스가 수정 된 경우에도 변경 될 수 없음)과 VOLATILE (기능이 컨텍스트 외부로 점프 함)을 이해한다고 생각합니다. 그것은 그것을 불렀습니다). 그 맞습니까? 그렇다면 안정적으로 표시되면 함수가 데이터베이스를 수정하지 않고 컨텍스트 외부의 데이터베이스에 액세스하지 않는다는 의미입니까? STABLE의 정의는 실제로 필요한 것보다 더 복잡한 것처럼 느껴집니다.
Brooks

PostgreSQL에는 실제로 몇 가지 문제가 있습니다 IMMUTABLE. 그것은 glibc(또는 최신 Pg에서 iconv) 데이터 정렬 정의를 변경하지 않을 것이라고 신뢰합니다 . 실제로는 그러한 변경을 감지 할 수있는 방법이 없습니다. 그것은 침묵 인덱스 손상 :(으로 이어질 수 등 다른 OS 버전간에 복제 할 때 주로 문제입니다.
크레이그 벨소리
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.