쿼리 엔진

쿼리 엔진 (SSE vs MSE)

single-stage 엔진(SSE)과 multi-stage 엔진(MSE)의 차이점과 각각 언제 사용해야 하는지 이해해요.

출처: 문서

본문

Pinot는 두 가지 지원되는 쿼리 엔진을 제공해요. single-stage 엔진(SSE) 은 scatter-gather 모델을 사용하며 단순 분석 쿼리의 기본값이에요. multi-stage 엔진(MSE) 은 분산 조인, 윈도우 함수, 서브쿼리, 집합 연산, 그리고 GROUPING SETS, ROLLUP, CUBE, GROUPING(), GROUPING_ID()를 포함한 많은 고급 SQL 연산을 지원해요.

SSE가 기본값인 이유는 가장 일반적인 Pinot 워크로드에 대해 오버헤드가 더 낮기 때문이에요. 이 기본값이 MSE가 실험적이라는 뜻은 아니에요. MSE는 단순 scatter-gather 실행 너머의 관계형 연산자가 필요한 쿼리를 위한 Pinot의 지원 엔진이에요.

타임라인: MSE는 Pinot 0.11.0에서 실험적 기능("v2 쿼리 엔진")으로 처음 도입되었고 Pinot 1.0.0에서 프로덕션 준비가 되었어요. 이후 릴리스에서는 null 처리(1.1.0), 성능 개선, 그리고 Lite Mode(1.4.0) 같은 기능이 추가되었어요. useMultistageEngine 같은 구성 속성에서 여전히 "v1"과 "v2"라는 표현을 볼 수 있어요.

빠른 결정 (Quick decision)

쿼리에 필요한 것이... 사용 이유
기본 필터링, 프로젝션, 집계 SSE 오버헤드 최저, 단순 scatter-gather 모델
GROUP BY GROUPING SETS, ROLLUP, CUBE, GROUPING(), GROUPING_ID() SSE 또는 MSE 두 엔진 모두 지원; multi-stage 기능도 필요하면 MSE 사용
JOIN MSE JOIN 지원은 multi-stage 엔진이 필요
윈도우 함수 MSE 윈도우 함수는 multi-stage 실행이 필요
Colocated 또는 파티셔닝된 조인 MSE 이는 multi-stage 패턴
복잡한 연산자 트리 또는 고급 SQL MSE 분산 쿼리 계획을 위해 설계됨

Single-stage 엔진 (SSE)

single-stage 엔진은 scatter-gather 실행 모델을 사용해요. 브로커가 쿼리를 받아 관련 서버로 퍼뜨리고, 각 서버는 로컬 세그먼트를 처리하며, 브로커는 부분 결과를 병합해요.

Single-stage 쿼리 엔진 (SSE)

SSE를 선택할 때:

  • 쿼리가 하나 이상의 테이블에 대한 단순 scatter-gather 읽기인 경우
  • 두 엔진 모두에서 사용 가능한 함수만 필요한 경우
  • 가장 낮은 개념적·운영적 오버헤드를 원하는 경우

SSE는 가장 일반적인 Pinot 워크로드(필터, 프로젝션, 그룹, 집계)의 기본 선택이에요.

Grouping sets

GROUPING SETS, ROLLUP, CUBE, GROUPING(), GROUPING_ID()는 두 엔진 모두에서 실행돼요. MSE에서 실행하려면 useMultistageEngine=true를 설정하세요. 문법, 제한, MSE 특정 제약은 GROUP BY를 참조하세요.

롤링 업그레이드 중에는 grouping sets를 사용하지 않는 기존 쿼리는 wire 호환성을 유지해요. grouping-set 쿼리는 모든 서버가 업그레이드된 후에만 사용하세요. 이전 서버는 grouping-set 요청 메타데이터를 이해하지 못해 오류나 잘못된 결과를 반환할 수 있어요.

Multi-stage 엔진 (MSE)

multi-stage 엔진은 데이터 교환 계층을 쿼리 엔진 계층과 분리해요. 쿼리를 서로 다른 서버 집합에서 실행되는 여러 하위 계획("스테이지")으로 나눠요.

Multi-stage 쿼리 실행 모델

MSE를 선택할 때:

  • JOIN, 윈도우 함수, 서브쿼리, 또는 다른 multi-stage 기능과 함께 grouping sets가 필요한 경우
  • 중간 스테이지가 있는 분산 쿼리 실행이 필요한 경우
  • 복잡한 ANSI SQL을 실행하는 경우

SSE 또는 외부 쿼리 엔진이 더 나은 워크로드:

  • 전체 데이터셋을 스캔하는 대규모 장기 실행 쿼리 — MSE는 spill-to-disk 없이 인-메모리로 실행되므로 매우 큰 중간 결과 집합이 사용 가능한 메모리를 초과할 수 있어요.
  • 많은 테이블에 걸친 무거운 ETL 스타일 조인 — 배치 지향 워크로드에는 Trino나 Spark 같은 외부 엔진을 고려하세요.
  • 단순 scatter-gather 쿼리(필터, 집계, top-K) — SSE가 더 낮은 오버헤드로 처리해요.

쿼리 처리 방법 (How queries are processed)

Pinot는 쿼리를 트리 구조로 연결된 스테이지로 나눠요.

  1. 잎(Leaf) 스테이지 — 테이블에서 읽어 다음 스테이지로 데이터를 보냄
  2. 중간(Intermediate) 스테이지 — 데이터 처리(예: 조인 수행) 후 결과를 전달
  3. 루트(Root) 스테이지 — 최종 결과를 클라이언트로 보냄

각 스테이지에는 병렬성 수준이 할당되며, 여러 서버가 그 스테이지를 병렬로 실행해요.

Null 처리

Pinot 1.1.0부터 multi-stage 엔진은 컬럼 기반 null 저장이 활성화되면 null 처리를 지원해요. 1.1.0 이전에는 모든 컬럼이 null 불허(non-nullable)로 처리되었어요.

MSE 활성화 방법

옵션 1: 쿼리 콘솔

Pinot 쿼리 콘솔에서 Use Multi-Stage Engine 체크박스를 선택하세요.

옵션 2: 쿼리 옵션

쿼리 맨 위에 쿼리 옵션을 추가하세요.

SET useMultistageEngine=true;
SELECT * FROM baseballStats LIMIT 10;

옵션 3: REST API

JSON 페이로드에 옵션을 전달하세요.

curl -X POST http://localhost:9000/sql -d '
{
  "sql": "select * from baseballStats limit 10",
  "trace": false,
  "queryOptions": "useMultistageEngine=true"
}'

함수 문서에서의 엔진 지원

함수 인덱스는 엔진 컬럼을 사용해 가용성을 표시해요.

  • Both — 두 엔진 모두에서 안전
  • Multi-stage only — MSE 필요
  • Varies — 특정 구현에 따라 다름

프로덕션에서 MSE 실행하기

프로덕션에서 MSE를 실행할 때 리소스 계획, 가드레일, 알려진 제한에 대한 운영 지침은 Run the Multi-Stage Engine in Production을 참조하세요.

더 알아보기 (Learn more)