주요 컨텐츠로 이동

SQL이 더 쉬워집니다: 새로운 파이프 구문 발표

모든 변환을 순서대로 표현하여 SQL을 더 간단하고 강력하게 만드세요

SQL Gets Easier: Announcing New Pipe Syntax

Published: April 30, 2025

공학3분 소요

Summary

  • SQL은 언어가 각 쿼리에서 어떤 데이터가 나와야 하는지 선언하기 때문에 성공했습니다. 엔진이 어떻게 실행해야 하는지를 정확히 지정하지 않습니다.
  • 그러나, SQL은 새로운 사용자가 배우거나 기존 사용자가 유지하기 어렵게 만들 수 있으며, 특히 많은 중첩 서브쿼리가 있는 경우에 그렇습니다.
  • 여기서 우리는 이를 돕기 위해 사용자가 독립적인 절을 순서에 상관없이 연속으로 구성할 수 있게 하는 새로운 구문을 발표합니다, 이는 DataFrames와 매우 유사합니다.

SQL은 수십 년 동안 구조화된 데이터 분석의 공용어가 되었으며, 우리는 최근 몇 년 동안 ANSI SQL 및 SQL을 Databricks에서 더 즐겁게 사용하게 만드는 다양한 확장을 지원하기 위해 많은 작업을 수행했습니다. 오늘, 우리는 기쁜 마음으로 SQL 파이프 구문을 발표합니다. 이는 최근 몇 년 동안 우리가 수행한 가장 큰 확장으로, SQL을 더욱 쉽게 작성하고 이해할 수 있게 만들었습니다. 이는 완전히 하위 호환성을 유지하는 방식입니다.

지금까지 SQL 자체에서의 주요 도전 과제 중 하나는 "논리"의 순서에 있습니다. 쿼리를 작성할 때, 많은 저자들은 다음과 같은 논리적 단계를 생각합니다: 쿼리할 테이블 목록을 식별하고, 이들을 결합하고, 원하지 않는 행을 필터링하고, 마지막으로 집계합니다. 이 논리적 순서는 다음과 같이 표현할 수 있습니다:

이 단계들에 대한 SQL 쿼리는 다음과 같이 보일 것입니다:

순서대로 단계를 작성하는 대신 (1, 2, 3), 우리는 대신 (3, 2, 1) 순서로 작성해야 합니다. 이것은 혼란스럽고, 각 쿼리에 더 많은 로직과 단계를 추가함에 따라 문제는 점점 더 복잡해집니다.

데이터프레임과 그것을 사랑하는 사람들

반면에, DataFrame에 대해 생각해봅시다. Apache Spark의 원래 인기의 큰 원인 중 하나는 Scala와 Python DataFrame API의 강력한 기능입니다. 프로그램은 이를 사용하여 로직을 자연스러운 순서의 단계로 표현할 수 있습니다. 소스 테이블에서 시작하여 사용자는 독립적이고 구성 가능한 연산을 차례로 연결하여 복잡한 데이터 변환을 명확하고 직관적인 순서로 쉽게 구축할 수 있습니다.

이 디자인은 가독성을 증진시키고 디버깅을 단순화하면서 유연성을 유지합니다. 이것이 Databricks가 데이터 관리 분야에서 지금까지 업계에서 크게 성장한 주요 이유이며, 이런 추세는 오늘날에도 계속 증가하고 있습니다.

다음은 PySpark 데이터프레임에서 동일한 로직이 어떻게 보이는지에 대한 것입니다:

이 접근법은 유연한 아이디어 반복을 지원합니다. 우리는 원본 데이터가 어떤 파일에 존재한다는 것을 알고 있으므로, 해당 데이터를 관계로 나타내는 데이터프레임을 바로 생성할 수 있습니다. 조금 생각한 후, 우리는 문자열 열에 의해 행을 필터링하고 싶다는 것을 깨닫습니다. 그래서 우리는 .filter 를 추가할 수 있습니다. 이전 DataFrame의 끝으로 이동합니다. 아, 그리고 우리는 마지막에 투영을 계산하고 싶으므로, 시퀀스의 끝에 그것을 추가합니다.

많은 사용자들이 SQL이 이와 같은 현대 데이터 언어와 더 유사하게 동작하기를 원합니다. 역사적으로 이것은 불가능했고, 사용자들은 한 가지 방식이나 다른 방식의 사고를 선택해야 했습니다.

새로운 SQL 파이프 구문을 소개합니다!

오늘날에 와서는 두 가지를 모두 가질 수 있게 되었습니다! 파이프 구문은 SQL을 쓰기도, 읽기도, 나중에 확장하기도 더 쉽게 만들며, 우리가 생각한 순서대로 동일한 단계를 단순히 사용할 수 있게 해주어 이 혼란에서 우리를 해방시킵니다.

VLDB 2024 컨퍼런스에서 Google은 이를 새로운 표준으로 제안하는 산업용 논문 을 발표했습니다. 쿼리 처리 엔지니어들이 이 기능을 구현하고 Apache Spark 4.0 (문서)과 Databricks 런타임 16.2 (문서) 이후 버전에서 기본적으로 활성화했습니다. 이는 일반 SQL 구문과 하위 호환성이 있습니다: 사용자는 이 구문을 사용하여 전체 쿼리를 작성하거나, 특정 하위 쿼리만 작성하거나, 또는 유용한 조합을 작성할 수 있습니다.

산업용 논문은 TPC-H 벤치마크의 쿼리 13을 첫 번째 예로 제공합니다:

파이프 구문을 사용하여 동일한 로직을 표현하면, 우리는 임의의 순서로 처음부터 끝까지 연산자를 순차적으로 적용합니다:

그리고 집계는 어떻게 작동하나요?

일반 SQL에서는 열 또는 표현식 값에 따라 행을 그룹으로 모으려면, 구축 중인 SQL 쿼리의 끝에 GROUP BY 절을 추가합니다. 수행할 집계는 쿼리의 맨 처음에 있는 SELECT 목록에 끼워져 있고, 이제 모든 표현식은 다음 중 하나여야 합니다:

  • 그룹화 키인 경우, GROUP BY 절은 표현식의 복사본(또는 별칭 참조 또는 순서)을 포함해야 합니다.
  • SUM, COUNT, MIN, 또는 MAX와 같은 집계 함수로, 입력 테이블 열을 기반으로 한 표현식을 받아들이는 SUM(A + B). 우리는 결과에 대한 투영을 계산할 수도 있습니다, 예를 들어 SUM(A) + 1.

이러한 카테고리 중 하나에 해당하지 않는 모든 SELECT 항목은 “표현식 X가 SELECT 목록에 나타났지만 그룹화되거나 집계되지 않았습니다.”와 같은 오류를 발생시킬 것입니다.

WHERE 절의 규칙도 변경됩니다:

  • 만약 이것이 GROUP BY 절 앞에 나타나면, 우리는 지정된 기준에 따라 행을 필터링한 후 그것들을 함께 집계합니다.
  • 그렇지 않으면, 쿼리는 유효하지 않고 우리는 이상한 오류를 받게 됩니다. 사용자는 대신 동일한 필터링 조건을 가진 HAVING 절을 작성해야 하며, 이는 GROUP BY 절 이후에만 나타나야 하며, 그 이전에는 나타나지 않아야 합니다.
  • QUALIFY 절은 또한 필터링을 수행하기 위해 문맥에 따라 별도의 구문을 이해하고 사용해야 하는 또 다른 예를 제공합니다.

파이프 구문은 각 집계 작업(그룹화 가능)을 언제든 적용할 수 있는 전용 단계로 분리함으로써 이 문제를 해결합니다. 이 단계 내에서는 집계 함수가 포함된 표현식만 나타날 수 있으며, 집계 함수는 |> SELECT 단계 내에 나타날 수 없습니다. SQL 작성자가 이러한 불변성 중 어느 것을 잊어버리면, 결과적으로 나오는 오류 메시지는 매우 명확하고 이해하기 쉽습니다.

또한 그룹화 표현식을 반복할 필요가 없습니다, 왜냐하면 우리는 그것들을 하나의 GROUP BY 절에 작성할 수 있기 때문입니다.

끝에 집계가 추가된 이전 예제를 살펴보면, 두 열 L, M이 있는 결과 테이블을 반환합니다:

서브쿼리로 재미있게

일반 SQL은 일반적으로 절이 특정 순서로 나타나야 하며, 반복해서 나타날 수 없습니다. SQL 쿼리의 결과에 추가 작업을 적용하려면, 원래 쿼리를 괄호로 묶어 테이블 서브쿼리를 사용하고, 이를 둘러싼 쿼리의 FROM 절에서 사용하는 방법입니다. 이 게시물의 시작 부분에 있는 쿼리는 이것의 간단한 예입니다.

이 중첩은 임의의 횟수로 발생할 수 있습니다. 예를 들어, TPC-DS 쿼리 23이 있습니다:

괄호와 들여쓰기의 모든 수준으로 인해 혼란스럽고 읽기 어려워집니다!

반면에, SQL 파이프 구문을 사용하면 테이블 서브쿼리가 전혀 필요하지 않습니다. 파이프 연산자는 어떤 순서로든 나타날 수 있으므로, 우리는 언제든지 새로운 것을 끝에 추가할 수 있고, 모든 단계는 여전히 동일한 방식으로 작동합니다.

이전 호환성으로 쉽게 시작하세요

파이프 구문은 작성자가 SQL을 작성하고, 읽고, 확장하는 방식을 재구성합니다. 일반 SQL이 작동하는 방식에서 이 새로운 패러다임으로 전환하는 것은 도전일 수 있습니다. 당신은 이전에 작성된 기존의 SQL 쿼리의 대량 본문을 유지 관리하고 가능하면 나중에 확장하는 책임이 있을 수도 있습니다. 우리는 이것을 어떻게 두 가지 SQL 구문으로 작동시킬 수 있을까요?

다행히도, 이것은 우리의 새로운 SQL 구문에서는 문제가 되지 않습니다. 이것은 일반 SQL과 완전히 상호 운용 가능하며, 어떤 쿼리(또는 테이블 서브쿼리)든지 어떤 구문을 사용하여 나타날 수 있습니다. SQL 파이프 구문을 사용하여 새로운 쿼리를 작성하기 시작하고 필요한 경우 이전 쿼리를 유지할 수 있습니다. 우리는 심지어 이전 쿼리의 테이블 서브쿼리를 새로운 구문으로 교체하기 시작하고, 나머지는 그대로 유지하여 이 게시물의 시작부터 TPC-H Q13의 일부만 업데이트할 수 있습니다.

SQL 파이프 연산자는 어떤 유효한 쿼리를 따를 수 있으므로, 기존의 일반 SQL 쿼리에 그것들을 추가하기 시작하는 것도 가능합니다. 예를 들어, 다음과 같은 접근 방식이 있습니다.

오늘 바로 시도해보세요!

SQL 파이프 구문은 Databricks Runtime 버전 16.2 이상에서 시도해 볼 준비가 되어 있습니다. 또는 Apache Spark 4.0을 다운로드하고 오픈 소스 세계에서 시도해 보세요. 구문은 SQL의 파이프 구문 산업 논문에 따르므로, 새 구문은 Google BigQuery 및 오픈 소스 ZetaSQL 프로젝트와 호환될 것입니다.

이 구문은 커뮤니티에서 화제를 모으기 시작하고 다른 곳에서 나타나기 시작하여, 지금과 앞으로의 이식성을 높입니다.

한 번 시도해 보고, SQL 쿼리를 작성하는 것을 새로운 사용자와 경험 많은 사용자 모두에게 더 간단하게 만들고, 복잡한 서브쿼리의 발생을 줄이고 명확하고 합성 가능한 연산자를 선호함으로써 미래의 가독성과 확장성을 더 쉽게 만드는 이점을 경험해 보세요.

 

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

게시물을 놓치지 마세요

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