JavaScript UDF 제한 사항

Snowflake 환경 내에서 안정성을 보장하기 위해 Snowflake는 JavaScript UDF에 다음과 같은 제한 사항을 적용합니다. 이러한 제한 사항은 UDF 생성 시 호출되지 않고, 오히려 UDF가 호출될 때 런타임에 호출됩니다. 이 항목에서는 일반 JavaScript UDF(사용자 정의 함수) 요구 사항 및 사용 세부 정보, 그리고 JavaScript UDF와 관련된 제한 사항을 다룹니다.

이 항목의 내용:

JavaScript 원본 코드의 최대 크기

Snowflake에서는 JavaScript UDF의 본문에서 JavaScript 소스 코드의 최대 크기를 제한합니다. Snowflake에서는 이 크기를 100KB로 제한할 것을 권장합니다. (코드는 압축된 형태로 저장되며 정확한 제한은 코드의 압축률에 따라 다릅니다.)

메모리를 너무 많이 사용하면 UDF가 실패하게 됩니다.

JavaScript UDF는 메모리를 너무 많이 사용하는 경우 실패하게 됩니다. 특정 제한은 변경될 수 있습니다. 너무 많은 메모리를 사용하면 오류가 반환됩니다.

완료하는 데 너무 오래 걸리면 UDF가 종료되고 오류가 반환됩니다.

완료하는 데 너무 오래 걸리는 JavaScript UDF는 종료되어 사용자에게 오류가 반환됩니다. 또한, 무한 루프에 들어가는 JavaScript UDF는 오류를 발생시킵니다.

과도한 스택 깊이로 인해 오류가 발생함

재귀로 인한 과도한 스택 깊이는 오류를 발생시킵니다.

전역 상태

일반적으로 Snowflake는 UDF 반복 사이에 JavaScript 전역 상태를 유지합니다. 그러나 함수 호출 사이에 사용할 수 있는 전역 상태에 대한 이전 수정 사항에 의존해서는 안 됩니다. 또한, 모든 행이 동일 JavaScript 환경 내에서 실행될 것이라고 가정해서는 안 됩니다.

실제로 전역 상태는 다음과 관련이 있습니다.

  • 복잡하거나 부담이 큰 초기화 논리. 기본적으로, 제공된 UDF 코드는 처리된 모든 행에 대해 평가됩니다. 해당 코드에 복잡한 논리가 포함되어 있으면 이는 비효율적일 수 있습니다.

  • idempotent가 아닌 코드가 포함된 함수. 일반적인 패턴은 다음과 같습니다.

    Date.prototype._originalToString = Date.prototype.toString;
    Date.prototype.toString = function() {
      /* ... SOME CUSTOM CODE ... */
      this._originalToString()
      }
    
    Copy

    이 코드는 처음 실행될 때 toString_originalToString 상태를 변경합니다. 이러한 변경 사항은 전역 상태로 유지되며 이 코드가 두 번째로 실행되는 경우, 재귀를 생성하는 방식으로 값이 다시 변경됩니다. toString 이 두 번째로 호출되면 코드가 무한히 반복됩니다(스택 공간이 소진될 때까지).

이러한 상황에서 권장되는 패턴은 JavaScript의 전역 변수 의미 체계를 사용하여 관련 코드가 한 번만 평가되도록 보장하는 것입니다. 예를 들면 다음과 같습니다.

var setup = function() {
/* SETUP LOGIC */
};

if (typeof(setup_done) === "undefined") {
  setup();
  setup_done = true;  // setting global variable to true
}
Copy

이 메커니즘은 코드 평가의 효과를 캐시하는 경우에만 안전합니다. 초기화 후에 전역 컨텍스트가 모든 행에 대해 보존된다는 보장은 없으며 비즈니스 논리는 이에 의존하지 않아야 합니다.

JavaScript 라이브러리

JavaScript UDF는 표준 JavaScript 라이브러리에 대한 액세스를 지원합니다. 여기에는 브라우저에서 일반적으로 제공하는 많은 오브젝트와 메서드가 제외됩니다. 추가 라이브러리를 가져오거나 포함하거나 호출하는 메커니즘이 없습니다. 모든 필수 코드는 UDF에 포함되어야 합니다.

또한, 기본 제공 JavaScript eval() 함수가 비활성화됩니다.

반환된 베리언트 크기 및 깊이

반환된 베리언트 오브젝트에는 크기 및 중첩 깊이 제한이 적용됩니다.

크기

현재 몇 메가바이트로 제한되어 있지만, 변경될 수 있습니다.

깊이

현재 중첩 깊이는 1000으로 제한되지만 변경될 수 있습니다.

오브젝트가 너무 크거나 너무 깊으면 UDF 호출 시 오류가 반환됩니다.

인자 및 반환 유형 제약 조건이 때때로 무시됨

인자 또는 반환 값에 대해 선언된 특정 유형의 특성은 UDF 호출 시 무시됩니다. 이러한 경우 수신된 값은 선언에 지정된 제약 조건을 준수하는지 여부에 관계없이 수신된 값으로 사용될 수 있습니다.

다음은 논리가 JavaScript로 작성된 UDF에 대해 무시됩니다.

  • VARCHAR 유형의 인자 길이

다음 예제의 코드는 arg1 인자와 반환 값이 1자 이하의 VARCHAR이어야 한다고 선언합니다. 하지만 값이 1자보다 긴 arg1 로 이 함수를 호출하면 제약 조건이 지정되지 않은 것처럼 성공합니다.

CREATE OR REPLACE FUNCTION tf (arg1 VARCHAR(1))
RETURNS VARCHAR(1)
LANGUAGE JAVASCRIPT AS 'return A.substr(3, 3);';
Copy