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을 쓰기도, 읽기도, 나중에 확장하기도 더 쉽게 만들며, 우리가 생각한 순서대로 동일한 단계를 단순히 사용할 수 있게 해주어 이 혼란에서 우리를 해방시킵니다.
VLDB 2024 컨퍼런스에서 Google은 이를 새로운 표준으로 제안하는 산업용 논문 을 발표했습니다. 쿼리 처리 엔지니어들이 이 기능을 구현하고 Apache Spark 4.0 (문서)과 Databricks 런타임 16.2 (문서) 이후 버전에서 기본적으로 활성화했습니다. 이는 일반 SQL 구문과 하위 호환성이 있습니다: 사용자는 이 구문을 사용하여 전체 쿼리를 작성하거나, 특정 하위 쿼리만 작성하거나, 또는 유용한 조합을 작성할 수 있습니다.
산업용 논문은 TPC-H 벤치마크의 쿼리 13을 첫 번째 예로 제공합니다:
파이프 구문을 사용하여 동일한 로직을 표현하면, 우리는 임의의 순서로 처음부터 끝까지 연산자를 순차적으로 적용합니다:
일반 SQL에서는 열 또는 표현식 값에 따라 행을 그룹으로 모으려면, 구축 중인 SQL 쿼리의 끝에 GROUP BY 절을 추가합니다. 수행할 집계는 쿼리의 맨 처음에 있는 SELECT 목록에 끼워져 있고, 이제 모든 표현식은 다음 중 하나여야 합니다:
이러한 카테고리 중 하나에 해당하지 않는 모든 SELECT 항목은 “표현식 X가 SELECT 목록에 나타났지만 그룹화되거나 집계되지 않았습니다.”와 같은 오류를 발생시킬 것입니다.
WHERE 절의 규칙도 변경됩니다:
파이프 구문은 각 집계 작업(그룹화 가능)을 언제든 적용할 수 있는 전용 단계로 분리함으로써 이 문제를 해결합니다. 이 단계 내에서는 집계 함수가 포함된 표현식만 나타날 수 있으며, 집계 함수는 |> 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의 도움을 받아 번역되었습니다. 원문이 궁금하시다면 여기를 클릭해 주세요)