주요 컨텐츠로 이동

SQL 사용자 정의 함수 소개

Introducing SQL User-Defined Functions

발행일: 2021년 10월 20일

제품3 min read

사용자 정의 함수(UDF)는 사용자가 Apache Spark™ SQL의 기본 기능을 확장할 수 있는 수단입니다. Databricks의 SQL은 1.3.0부터 Scala, Java, Python 및 R 프로그래밍 언어로 작성된 외부 사용자 정의 함수를 지원해 왔습니다. 외부 UDF는 매우 강력하지만 몇 가지 주의사항이 따릅니다.

  • 보안. 외부 언어로 작성된 UDF는 위험하거나 악의적인 코드를 실행할 수 있습니다. 이를 위해서는 UDF를 생성할 수 있는 사용자를 엄격하게 제어해야 합니다.
  • 성능. UDF는 Catalyst Optimizer에게 블랙박스와 같습니다. Catalyst는 UDF의 내부 작동 방식을 알지 못하므로 SQL 쿼리 컨텍스트 내에서 UDF의 성능을 개선하기 위한 작업을 수행할 수 없습니다.
  • SQL 사용성. SQL 사용자에게는 호스트 언어로 UDF를 작성한 다음 Spark에 등록하는 것이 번거로울 수 있습니다. 또한, 많은 사용자가 SQL에 추가하고 싶어하는 몇 가지 간단한 확장 기능이 있는데, 외부 UDF를 개발하는 것은 과도합니다.

위의 제한 사항을 해결하기 위해 새로운 형태의 UDF인 SQL UDF를 소개하게 되어 기쁩니다. DBR 9.1 LTS에서 사용할 수 있는 SQL UDF는 SQL의 표현력을 완전히 사용하여 정의되며 SQL 컴파일러에 완전히 투명합니다.


Databricks Lakehouse Platform의 내부 작동 방식을 알아보려면 데이터 레이크하우스가 차세대 데이터 웨어하우스인 이유 전자책을 확인하세요.

SQL UDF 사용의 이점

SQL UDF는 Databricks의 SQL에 대한 간단하면서도 강력한 확장 기능입니다. 함수로서 쿼리 구성을 단순화하는 추상화 계층을 제공하여 SQL 쿼리를 더 읽기 쉽고 모듈화합니다. SQL이 아닌 언어로 작성된 UDF와 달리 SQL UDF는 SQL 사용자가 생성하기에 더 가볍습니다. SQL 함수 본문은 쿼리 옵티마이저에 투명하므로 외부 UDF보다 성능이 뛰어납니다. SQL UDF는 임시 함수 또는 영구 함수로 생성할 수 있으며 여러 쿼리, 세션 및 사용자 간에 재사용할 수 있고 ACL(액세스 제어 언어)을 통해 액세스 제어가 가능합니다. 이 블로그에서는 예제를 통해 SQL UDF의 몇 가지 주요 사용 사례를 살펴보겠습니다.

상수로 사용되는 SQL UDF

상상할 수 있는 가장 간단한 함수인 상수부터 시작하겠습니다. 코드에 리터럴을 사용하면 가독성이 떨어지고, 나중에 상수가 변경될 수도 있기 때문에 사용하지 않는 것이 좋다는 것을 모두 알고 있습니다. 따라서 한 곳에서만 변경하고 싶을 것입니다.

외부 UDF에 익숙하다면 눈에 띄는 몇 가지 차이점을 볼 수 있습니다.

  1. SQL UDF는 매개변수 목록이 비어 있더라도 매개변수 목록을 정의해야 합니다. 상수는 매개변수를 받지 않습니다.
  2. 함수는 반환할 데이터 유형도 선언합니다. 이 경우 STRING입니다.
  3. 함수의 구현은 함수 정의의 일부입니다.
  4. LANGUAGE SQL을 지정하여 SQL UDF임을 나타냅니다. 하지만 실제로 필요하지는 않습니다. RETURN 절만으로도 충분하므로 이 옵션을 선택 사항으로 만들었습니다.

이러한 차이점 외에도 외부 UDF와 동일한 점이 많이 있습니다.

  • 함수를 교체할 수 있습니다. 자세한 내용은 나중에 설명합니다.
  • 함수를 설명하는 주석을 추가할 수 있습니다. 위에 표시된 대로입니다.
  • 현재 세션 내에서만 사용할 수 있는 임시 함수를 만들 수도 있습니다.

함수를 사용해 보겠습니다.

예상대로 작동합니다. 하지만 내부적으로는 어떻게 작동할까요?

멋지네요! SQL 컴파일러가 함수 호출을 상수로 대체했습니다.
이는 적어도 이 SQL UDF는 성능에 전혀 비용이 들지 않는다는 것을 의미합니다.

이제 또 다른 일반적인 사용 패턴을 살펴보겠습니다.

표현식을 캡슐화하는 SQL UDF

일부 내장 함수의 명명 규칙이 마음에 들지 않는다고 상상해 보세요. 다른 제품에서 많은 쿼리를 마이그레이션 중인데, 해당 제품은 함수 이름과 동작이 다를 수 있습니다. 또는 단순히 SQL 쿼리에서 길고 복잡한 표현식을 반복해서 복사하여 붙여넣는 것이 싫을 수도 있습니다. 그래서 이를 수정하고 싶습니다.

SQL UDF를 사용하면 원하는 이름으로 새 함수를 간단히 만들 수 있습니다.

여기서 사용된 새로운 구문을 살펴보겠습니다.

  • 이 함수는 인수를 받으며, 매개변수는 이름, 유형 및 선택적 주석으로 정의됩니다.
  • CONTAINS SQL 절은 선택 사항이지만 함수가 테이블의 데이터를 읽거나 수정하지 않음을 알려줍니다. 이것이 기본 설정이므로 일반적으로 지정하지 않습니다.
  • DETERMINISTIC도 선택 사항이며 함수가 동일한 인수에 대해 항상 동일한 결과 집합을 반환함을 알려줍니다. 이 절은 현재로서는 문서화 목적입니다. 하지만 미래에는 특정 컨텍스트에서 결정적이지 않은 함수를 차단하는 데 사용될 수 있습니다.
  • RETURN 절에서 매개변수는 이름으로 참조되었습니다. 아래의 더 복잡한 시나리오에서는 매개변수를 함수 이름으로 모호성을 해소할 수 있음을 알 수 있습니다. 당연히 함수 본문으로 임의로 복잡한 표현식을 사용할 수 있습니다.

작동할 뿐만 아니라…

… 잘 작동합니다.

물리적 계획에서 lpad, hex, least 및 greatest 함수가 직접 적용되는 것을 볼 수 있습니다. 이것은 함수 시리즈를 직접 호출할 때 얻는 것과 동일한 계획입니다.

SQL 함수를 SQL 함수로 구성할 수도 있습니다.

테이블에서 읽는 SQL UDF

SQL UDF의 또 다른 일반적인 용도는 조회 코드를 작성하는 것입니다. 간단한 조회는 RGB 색상 코드를 영어 색상 이름으로 디코딩하는 것일 수 있습니다.

알겠습니다. 하지만 세상에는 두 가지 색상보다 훨씬 더 많은 색상이 있습니다. 그리고 이 번역을 양방향으로 원하므로 실제로 조회 테이블에 있어야 합니다.

여기에는 여러 가지 새로운 개념이 적용되었습니다.

  • SQL UDF를 REPLACE할 수 있습니다. 이를 허용하려면 새 함수가 이전 함수의 시그니처와 일치해야 합니다. 함수의 시그니처는 매개변수의 수와 유형으로 정의됩니다.
  • 이 함수는 테이블에서 정보를 조회하므로 선택적으로 READS SQL DATA를 사용하여 문서화할 수 있습니다. 아무것도 지정하지 않으면 SQL 컴파일러가 올바른 값을 파생하지만, 거짓으로 CONTAINS SQL이라고 명시해서는 안 됩니다.
  • SQL SECURITY DEFINER는 또 다른 선택적 절로, colors 테이블에 액세스하는 쿼리가 함수 소유자의 권한을 사용함을 나타냅니다. 따라서 함수는 테이블의 보안을 손상시키지 않고 공개적으로 실행될 수 있습니다.
  • 함수가 소유자의 권한으로 작동하는 것처럼 생성 시점의 현재 데이터베이스를 사용하여 항상 구문 분석됩니다.
  • `rgb`는 숫자의 열 이름입니다. `from_rgb`.`rgb`로 매개변수를 한정하여 열이 아닌 매개변수 참조를 의미함을 명확히 합니다.

물리적 계획은 어떻게 보일까요? 중첩 루프 조인 결과를 생성하는 외부 UDF를 사용하는 것이 귀중한 리소스를 소모하는 끔찍한 방법이라는 것을 쉽게 알 수 있습니다.

이 경우 Catalyst는 중첩 루프 조인 대신 브로드캐스트 해시 조인을 선택했습니다. SQL UDF의 내용을 이해하기 때문에 그렇게 할 수 있습니다.

지금까지 논의된 모든 예제는 단일 값을 반환하는 스칼라 값 함수를 사용했습니다. 해당 결과는 구조체, 배열 및 맵의 복잡한 조합을 포함하여 어떤 유형이든 될 수 있습니다. 또한 논의할 다른 유형의 UDF가 있습니다. 바로 테이블 값 UDF입니다.

SQL 테이블 UDF

뷰에 인수가 있다고 상상해 보세요! 사용자 제공 값을 기반으로 하는 복잡한 술어를 캡슐화할 수 있습니다. SQL 테이블 UDF는 바로 그것입니다. 이름은 다르지만 매개변수가 있는 뷰입니다.

위의 색상 매핑이 고유하지 않다고 가정해 보겠습니다. 적어도 색상 이름이 언어마다 다르다는 것을 확인할 수 있습니다.

따라서 `from_rgb` 함수는 이름 배열 또는 관계를 반환하도록 수정해야 합니다.

보시다시피 스칼라 함수와의 유일한 차이점은 더 복잡한 RETURNS 절입니다. 뷰와 달리 SQL UDF는 반환되는 관계의 시그니처 선언을 의무화합니다.

  • TABLE는 함수가 관계를 반환함을 지정합니다.
  • TABLE 절에는 각 반환 열의 이름과 열의 데이터 유형이 포함되어야 합니다.
  • 선택적으로 반환 열에 대한 주석을 지정할 수 있습니다.

사용자 정의 테이블 함수는 DBR에 새로 추가되었습니다. 호출 방법을 살펴보겠습니다.

가장 간단한 형태에서 테이블 함수는 뷰가 참조되는 방식과 동일한 장소에서 호출됩니다. 유일한 차이점은 함수 인수를 포함하는 필수 중괄호입니다. 이 함수는 리터럴 인수로 호출되지만 인수는 표현식, 심지어 스칼라 하위 쿼리일 수도 있습니다.

그러나 가장 강력한 기능은 일반적으로 상관 크로스 조인인 조인에서 SQL 테이블 UDF를 사용하는 것입니다.

여기서 인수는 FROM 절의 이전(측면) 관계를 참조합니다(상관 관계). 새로운 LATERAL 키워드는 Catalyst가 이러한 열을 해석할 수 있도록 허용합니다. 또한 결과 시그니처에 정의된 대로 열의 이름을 지정하고 선택적으로 함수 이름으로 한정하여 테이블 함수의 결과에 참조할 수 있다는 점에 유의하십시오.

관리

당연히 SQL UDF는 기존 GRANT, REVOKE, SHOW, DESCRIBE 및 DROP 문에서 완벽하게 지원됩니다.

더 자세히 설명할 가치가 있는 문은 DESCRIBE입니다.

기본 describe는 예상대로 작동하지만 확장된 DESCRIBE는 훨씬 더 많은 세부 정보를 추가합니다.

전망

지금까지 설명한 내용은 SQL UDF의 초기 기능입니다. 현재 고려 중인 향후 확장 기능에는 다음이 포함됩니다.

  • SQL PATH: 데이터베이스에서 함수 라이브러리를 생성하고 파일 시스템에서처럼 다른 라이브러리에서 구독할 수 있습니다.
  • UDF 오버로딩.
  • 매개변수에 대한 기본값이 있는 UDF.

SQL UDF는 SQL 사용성을 크게 향상시킨 기능이며 이 블로그에서 설명한 대로 다양한 방식으로 사용될 수 있습니다. Databricks SQL에서 또는 데이터 엔지니어링 작업에 Photon을 사용하여 더 창의적인 방법으로 SQL UDF를 활용하는 방법을 생각해 보세요. 여기서 노트북을 사용해 보고 자세한 내용은 설명서를 참조하세요.

(이 글은 AI의 도움을 받아 번역되었습니다. 원문이 궁금하시다면 여기를 클릭해 주세요)

게시물을 놓치지 마세요

관심 있는 카테고리를 구독하고 최신 게시물을 받은편지함으로 받아보세요