쿼리 옵션
쿼리 옵션 (Query Options)
실행, 진단, 리소스 사용을 형성하는 쿼리 수준 스위치예요.
출처: 문서
본문
쿼리 옵션은 실행 엔진을 선택하고, 런타임 제한을 제어하며, 진단을 조정할 수 있게 해주는 쿼리별 스위치예요.
가장 중요한 옵션
useMultistageEngine고급 SQL 기능이 필요한 쿼리에 multi-stage 엔진을 선택해요.timeoutMsPinot가 쿼리에 사용할 시간의 상한을 정해요.clientQueryId추적과 취소를 위해 쿼리에 안정적인 식별자를 부여해요.explainPlanVerbosePinot에 더 풍부한 계획 출력을 요청해요.maxExecutionThreads비싼 쿼리의 동시성을 제한해요.numGroupsLimit,minSegmentGroupTrimSize,minServerGroupTrimSize,accurateGroupByWithoutOrderBy같은 group-by 메모리/정확도 노브(아래 Grouping algorithm 참조).
SET useMultistageEngine = true;
SET timeoutMs = 5000;
SET clientQueryId = 'query-2026-03-24-001';
SELECT city, COUNT(*)
FROM stores
GROUP BY city
LIMIT 10;
옵션 이름
문서화된 키는 정규 camelCase를 사용해요(예: timeoutMs, useMultistageEngine, minSegmentGroupTrimSize). Pinot는 SET / OPTION 절을 파싱할 때 인식된 옵션 이름을 대소문자 구분 없이 그 정규 형태로 해석하므로 SET timeoutms = 5000은 timeoutMs처럼 처리돼요.
아래 표의 정규 이름을 사용하는 것이 좋아요. 데이터 쿼리의 경우 클러스터 수준 pinot.broker.query.option.validationMode가 SQL SET 문이나 레거시 OPTION(...) 절을 통해 제공된 알 수 없는 키를 제어해요. 기본값 NONE은 호환성을 위해 보존하고, WARN은 알 수 없는 키를 로깅하며, REJECT는 쿼리를 실패시켜요. 가까운 오타는 timeoutMs 같은 인식된 옵션에 대한 제안을 만들 수 있어요. SQL 쿼리는 내부 rlsFilters* 옵션을 설정할 수도 없어요. 브로커는 필요할 때 파싱 후 행 수준 보안 옵션을 추가해요.
이 검증은 SQL DQL 경로에 한정돼요. 자유 형식 옵션은 REST/JSON queryOptions 필드에서 하위 호환성을 유지하며, INSERT INTO FILE 같은 DML SET 속성은 자유 형식으로 남아요. 통합이 사용자 지정 옵션 이름에 의존한다면 SQL 텍스트에 넣는 대신 요청의 queryOptions 필드로 보내세요.
기본 LIMIT 동작, group-by 꼬리 트리밍, ORDER BY 대 정렬 없는 group-by에 대해서는 Querying Pinot를 참조하세요.
SQL 옵션 정책
운영자는 cluster config API를 통해 pinot.broker.query.option.validationMode와 pinot.broker.query.option.legacySyntaxMode를 변경할 수 있어요. 둘 다 재시작 없이 실행 중인 브로커에 적용돼요. 전자는 데이터 쿼리의 알 수 없는 SQL 옵션 이름에 대해 NONE(기본값), WARN, REJECT를 받아요. 후자는 DML을 포함한 모든 문 유형의 OPTION(key=value) 접미사에 대해 ALLOW(기본값), IGNORE, REJECT를 받아요. REJECT는 호출자가 SQL SET을 대신 사용하도록 안내해요. 롤링 업그레이드 중에는 IGNORE나 REJECT를 설정하기 전에 모든 브로커가 legacySyntaxMode를 지원할 때까지 기다리세요. 이전 브로커는 접미사를 계속 적용해요.
요청 게이트웨이가 SQL 텍스트가 신뢰된 요청 옵션을 덮어쓰지 못하게 해야 한다면 요청의 queryOptions(REST)나 gRPC 메타데이터에 sqlOptionsMode를 전달해요. ALLOW(기본값)는 SQL SET과 레거시 OPTION(...) 값을 요청 옵션 위에 병합하고, IGNORE는 SQL에 포함된 옵션을 버리며, REJECT는 해당 키와 함께 QUERY_VALIDATION을 반환해요. 예를 들어 REST 요청은 sql 문자열과 함께 "queryOptions": "sqlOptionsMode=IGNORE;timeoutMs=5000"을 포함할 수 있어요. 이 모드는 SQL 내부에 제공될 때는 인정되지 않아요. 잘못된 모드는 SQL에 옵션이 없어도 QUERY_VALIDATION으로 실패해요.
옵션을 언제 쓰는가
테이블 구성을 변경하지 않고 동작을 바꾸고 싶을 때 쿼리 옵션을 사용해요.
일반적인 경우:
- 사용자 대면 요청의 타임아웃 낮추기
- 조인이 필요한 쿼리에 대해 multi-stage 실행 강제하기
- 로그와 취소를 위한 사용자 지정 쿼리 ID 연결
- 단일 쿼리의 실행 리소스 넓히기/좁히기
더 깊은 노브가 있는 곳
일부 쿼리 동작은 원시 옵션 목록 대신 전용 페이지로 제어돼요.
- 속도 제한에는 Query quotas 사용
- 쿼리를 중지해야 할 때는 Query cancellation 사용
- 결과 집합이 너무 클 때는 Cursor pagination 사용
이 페이지가 다룬 내용
이 페이지는 주요 쿼리 수준 스위치, 설정하는 이유, 관련 제어를 처리하는 전용 페이지를 다뤘어요.
다음 단계
쿼리를 추적하거나 중지해야 한다면 Query cancellation을 읽어 보세요. 결과 전달을 형성해야 한다면 Cursor pagination을 읽어 보세요.
지원되는 쿼리 옵션
| Key | 설명 | 기본 동작 |
|---|---|---|
| timeoutMs | 쿼리의 타임아웃(밀리초) | 테이블/브로커 수준 타임아웃 사용 |
| extraPassiveTimeoutMs | multi-stage 쿼리의 경우, Pinot가 상위 스테이지나 mailbox 데이터를 기다릴 때 사용하는 수동적(passive) 데드라인에 이 밀리초를 더함. timeoutMs의 능동적 쿼리 데드라인은 바꾸지 않음. |
브로커 수준 구성(기본값 100) |
| enableNullHandling | 고급 null 처리를 활성화함(Null value support 참조, 0.11.0부터) | false (비활성) |
| explainPlanVerbose | EXPLAIN 쿼리에 대해 상세 결과 반환(0.11.0부터) |
false (상세하지 않음) |
| useMultistageEngine | 쿼리를 실행하는 데 multi-stage 엔진 사용(0.11.0부터) | false (single-stage 엔진 사용) |
| sqlOptionsMode | SQL SET 또는 레거시 OPTION(...)에 포함된 옵션에 대한 요청 수준 정책: ALLOW, IGNORE, REJECT. REST queryOptions나 gRPC 메타데이터에 제공( SQL 내부 아님). |
ALLOW (SQL 옵션이 요청 옵션을 덮어씀) |
| useApproximateFunction | 적격한 정확 distinct-count 및 percentile 집계를 SMART 변형으로 재작성할지 true, 정확하게 유지할지 false로 설정. 단일-stage 전용. |
테이블, 클러스터, 브로커 설정; 어디에도 없으면 false |
| useMSEToFillEmptyResponseSchema | 0행을 반환하는 single-stage 쿼리에 대해 multi-stage 엔진 컴파일러로 더 정확한 빈 결과 스키마를 채우려 시도. | false |
| enableMaterializedViewRewrite | 적격 single-stage 쿼리에서 브로커 측 물리화 뷰 재작성이 허용되는지 제어. 생략 시 기본 활성. | true |
| maxExecutionThreads | 쿼리 실행에 사용할 최대 스레드 수. 비싼 쿼리의 리소스 사용 제한에 유용. | 설정 시 쿼리 값 사용; 아니면 서버 기본값/자동 선택 |
| numReplicaGroupsToQuery | replica-group 기반 라우팅이 활성화될 때 여러 replica-group을 조회하는 데 사용(0.11.0부터) | 1 (같은 replica-group 내 서버만 조회) |
| useFixedReplica | 각 세그먼트를 쿼리에 대해 일관된 복제본으로 라우팅. 테이블/브로커 수준의 fixed-replica 설정을 덮어씀. | 테이블/브로커 수준 설정; 둘 다 없으면 false |
| sortAggregateLimitThreshold | group-by 쿼리에서 모든 group key로 정렬할 때 쿼리 LIMIT가 이 임계값 아래이면 sort-aggregation 사용. |
10000 |
| sortAggregateSingleThreadedNumSegmentsThreshold | 병합할 세그먼트 수가 이 임계값 아래이면 병렬 쌍별 병합 대신 단일 스레드 순차 결합 사용. | CPU 코어 수 |
| numGroupsLimit | group-by 쿼리에서 새 그룹 수용을 멈추기 전 각 쿼리 연산자가 유지하는 그룹 수 상한. leaf와 intermediate 스테이지 모두에 적용. | 서버 수준 구성(기본값 100000) |
| numGroupsWarningLimit | group-by 쿼리에서 쿼리 연산자가 축적하는 그룹 수의 경고 임계값. 도달하면 경고 로깅 및 numGroupsWarningLimitReached=true 설정. |
서버 수준 구성(기본값 150000) |
| errorOnNumGroupsLimit | multi-stage group-by 쿼리에서 numGroupsLimit에 도달하면 부분 결과 대신 예외 발생. |
false |
| allowReverseOrder | single-stage 선택 쿼리에서 정렬된 세그먼트를 ORDER BY ... DESC에 대해 내림차순으로 읽는 것을 허용. |
false |
| minInitialIndexedTableCapacity | group-by 쿼리에서 IndexedTable 인스턴스 생성 시 사용하는 최소 초기 용량. |
128 |
| minSegmentGroupTrimSize | group-by 쿼리에서 세그먼트 수준 그룹 트리밍 시 유지할 최소 그룹 수. | 서버 수준 구성 |
| minServerGroupTrimSize | group-by 쿼리에서 서버 수준 그룹 트리밍 시 유지할 최소 그룹 수. | 서버 수준 구성 |
| serverReturnFinalResult | group key가 서버 파티셔닝되었을 때 서버가 집계에 대해 중간 결과 대신 최종 결과를 직접 반환하도록 요청. | 단일 서버 조회 시 true, 아니면 false |
| serverReturnFinalResultKeyUnpartitioned | group key가 서버 파티셔닝되지 않았지만 집계 컬럼이 서버 파티셔닝되었을 때 사용. distinct count에 특히 유용. | false |
| skipIndexes | 어떤 인덱스를 건너뛸지(즉 스캔), 컬럼별로 지정. URL 파라미터 형식: skipIndexes='col1=inverted,range&col2=inverted'. 건너뛸 유형: sorted, range, inverted, H3. |
null/empty (모든 사용 가능한 인덱스 사용) |
| vectorNprobe | IVF_FLAT, IVF_PQ, IVF_ON_DISK 벡터 검색에서 ANS 후보 수집 전 세그먼트당 조사할 inverted list 수. HNSW 및 정확-스캔 대체 경로에서는 무시. | IVF의 경우 4; HNSW 및 정확-스캔 대체에서 무시 |
| vectorExactRerank | ANN 인덱스를 사용하는 벡터 검색에서 최종 top-K 반환 전 ANN 후보를 forward index의 정확 거리로 재점수화. | IVF_PQ의 경우 true; HNSW 및 IVF_FLAT의 경우 false |
| vectorMaxCandidates | vectorExactRerank=true일 때 정확 재순위화 전 검색할 ANN 후보 수. |
정확 rerank 활성 시 topK * 10 |
| vectorDistanceThreshold | top-K 제한 대신 이 거리 임계값 내의 모든 결과를 반환. VECTOR_SIMILARITY 쿼리에 적용. |
미설정 (top-K 검색 사용) |
| vectorEfSearch | HNSW 검색에서 그래프 순회가 방문하는 노드 수(검색 빔 폭). IVF 및 정확-스캔 대체 경로에서 무시. | 인덱스 구성에서(미설정 시 topK 기본) |
| vectorUseRelativeDistance | HNSW 검색에서 경쟁적(상대 거리) 가지치기 토글. 비-HNSW 인덱스에서 무시. | true |
| vectorUseBoundedQueue | HNSW 검색에서 bounded top-K collector 토글. 비-HNSW 인덱스에서 무시. | true |
| skipPlannerRules | 기본 활성화된 쿼리 플래너 규칙 중 어떤 것을 비활성화할지. 쉼표 구분 규칙 이름: skipPlannerRules='FilterProjectTranspose,PruneEmptySort'. |
null/empty (기본 활성 규칙을 건너뛰지 않음) |
| usePlannerRules | 기본 비활성인 규칙 중 어떤 것을 사용할지. 쉼표 구분: usePlannerRules='AggregateJoinTransposeExtended,SortProjectTranspose'. |
null/empty (기본 비활성 규칙 사용 안 함) |
| skipUpsert | upsert 활성 테이블에서 upsert 효과를 건너뛰고 모든 레코드를 조회. | false (대체된 레코드 제외) |
| upsertViewFreshnessMs | SNAPSHOT 일관성 모드를 사용하는 upsert 테이블에서 upsert 뷰의 쿼리 시 신선도 창을 덮어씀. |
테이블의 upsertViewRefreshIntervalMs 사용 |
| skipUpsertView | upsert 테이블 디버깅: SYNC/SNAPSHOT 일관성 모드가 유지하는 일관된 upsert 뷰를 우회해 NONE 모드처럼 조회. |
false |
| useStarTree | star-tree 인덱스 디버깅에 유용(0.11.0부터). | true (가능하면 star-tree 사용) |
| AndScanReordering | 상세 설명 참조. | 비활성 |
| maxRowsInJoin | 조인 연산에 허용되는 최대 행 수. 조인의 오른쪽 입력에 대한 해시 테이블 빌드 단계와 왼쪽 입력과 매칭 후 방출되는 조인 행 수 모두에 적용. | 클러스터 구성 기본, 미설정 시 2^20 (1024*1024) |
| inPredicatePruningThreshold | IN 조건자에서 Pinot가 값 기반 또는 bloom 필터 세그먼트 프루닝을 시도하는 최대 값 수를 덮어씀. |
서버 inpredicate.threshold 설정(기본 10) |
| inPredicatePreSorted | (STRING 컬럼만) IN 절의 값이 이미 정렬되어 있어 Pinot가 쿼리 시 다시 정렬할 필요가 없음을 표시. | false |
| inPredicateLookupAlgorithm | (STRING 컬럼만) IN 절 값의 사전 ID를 찾는 알고리즘: DIVIDE_BINARY_SEARCH, SCAN, PLAIN_BINARY_SEARCH. |
DIVIDE_BINARY_SEARCH |
| maxServerResponseSizeBytes | 쿼리에 대해 서버별 직렬화 응답의 최대 길이(Long). | 쿼리 옵션 → 테이블 구성 → 브로커 구성 우선순위 |
| maxQueryResponseSizeBytes | 쿼리에 대해 모든 서버에 걸친 최대 직렬화 응답 크기(Long). 이 값을 쿼리를 처리하는 모든 서버에 균등 분할. | 위와 같은 우선순위 |
| filteredAggregationsSkipEmptyGroups | 기본 쿼리 필터와 일치하지만 필터링된 집계 FILTER (WHERE ...) 절과 일치하지 않는 그룹 계산을 피하려면 true. |
false (표준 SQL처럼 모든 그룹 계산) |
| dropResults | 응답에서 resultTable을 버리도록 dropResults=true 설정. 민감한 데이터가 포함된 결과로 고객 쿼리를 메타데이터 전용으로 문제 해결하는 데 사용. |
false |
| skipUnavailableServers | 디스패치가 실패하면 나머지 서버로 쿼리를 계속 보내도록 skipUnavailableServers=true 설정. |
false |
| ignoreMissingSegments | 라우팅된 세그먼트가 서버에서 사용 불가능할 때 SERVER_SEGMENT_MISSING 예외 무시. |
false |
| sampler | 테이블 구성에서 명명된 테이블 샘플러를 선택. 세그먼트 샘플 부분집합에 대해 쿼리 실행. 예: SET sampler='small'. |
null/empty (일반 라우팅) |
| clientQueryId | 쿼리의 사용자 지정 상관 ID 및 쿼리 취소 정의. | null/empty |
| applicationName | 쿼리를 명명된 애플리케이션에 할당해 애플리케이션 수준 쿼리 할당량에 사용. Query Quotas API와 함께 사용. | null/empty (애플리케이션 이름 없음) |
| accurateGroupByWithoutOrderBy | ORDER BY/HAVING 없는 SSE GROUP BY ... LIMIT에서 서버·브로커 축소 중 사전순으로 가장 작은 group key를 유지해 결정적 부분집합 유지. |
false |
| optimizeMaxInitialResultHolderCapacity | single-stage GROUP BY에서 단일 값 그룹핑 컬럼의 등식/IN 조건자를 사용해 초기 result-holder 용량을 줄임. |
false |
| traceRuleProductions | 플래너 규칙 생성을 추적. SET traceRuleProductions=true로 성공적으로 새 관계를 생성한 플래너 규칙 및 전후 관계 서브트리를 수집·반환. |
false |
| excludeVirtualColumns | 쿼리에서 가상 컬럼($로 시작)을 무시하고 싶을 때 사용(예: NATURAL JOIN에서 조인 조건 매칭에 참여하면 안 될 때). MSE에서 구현. |
false (기본적으로 모든 쿼리에서 조인 매칭 중 가상 컬럼 포함) |
| useSpools | multi-stage 쿼리에 대해 스테이지 레벨 스풀링 활성화. 동등한 스테이지를 반복 실행 대신 재사용 가능. stage-level-spooling 참조. | 브로커 수준 구성(기본 false) |
| usePhysicalOptimizer | MSE용 Physical Optimizer 활성화. 불필요한 Exchange(셔플)를 자동 제거/단순화. useMultistageEngine=true와 함께 사용해야 함(1.4.0 도입). |
false (비활성) |
| unnestColumnPruning | multi-stage UNNEST 쿼리에서 논리 플래너 경로의 미사용 통과 컬럼을 UNNEST 출력에서 제거. usePhysicalOptimizer=true면 무시. |
브로커 수준 구성(기본 false) |
| sortExchangeCopyThreshold | multi-stage ORDER BY ... LIMIT에서 유효 fetch가 이 정수 임계값 이하일 때 sort-and-limit을 sort exchange 아래로 푸시. |
브로커 수준 구성(기본 10000) |
| inferRealtimeSegmentPartition | 파티셔닝된 실시간 테이블의 multi-stage 엔진에서 저장된 세그먼트-파티션 메타데이터에 의존할 수 없을 때 실시간 세그먼트 이름에서 세그먼트 파티션 추론. | false |
| useLiteMode | Multi-stage 엔진 Lite Mode 활성화: scatter-gather 패러다임으로 MSE 쿼리 실행, leaf 스테이지 인스턴스당 반환 행 제한 구성 가능(기본 100k). useMultistageEngine=true와 usePhysicalOptimizer=true 필요(1.4.0 도입). |
false (비활성) |
| liteModeLeafStageLimit | Lite Mode에서 leaf 스테이지 worker가 반환할 수 있는 최대 레코드 수를 덮어씀. 양의 정수여야 함. | 브로커 수준 구성(기본 100000) |
| liteModeLeafStageFanOutAdjustedLimit | Lite Mode에서 fan-out 조정 leaf-스테이지 제한을 양의 정수로 덮어씀. | 브로커 수준 구성(미설정/비양수 시 비활성) |
| runInBroker | Lite Mode에서 non-leaf 스테이지를 어디서 실행할지 제어. true면 scatter-gather 실행 모델을 보존하기 위해 브로커에서 실행. |
브로커 수준 구성(Lite Mode 활성 시 기본 true) |
| useLeafServerForIntermediateStage | multi-stage 쿼리에서 모든 활성 서버에서 선택하는 대신 leaf 스테이지에 선택된 것과 같은 서버를 intermediate 스테이지의 worker로 사용. | false |
| streamStats | multi-stage 쿼리에서 브로커-서버 디스패치를 레거시 unary submit 경로 대신 스트리밍 SubmitWithStream 통계 경로로 전환. |
브로커 수준 구성(기본 false) |
| inferPartitionHint | multi-stage 조인에서 조인된 테이블로부터 파티션 정보를 추론해 colocated 실행을 사용. 브로커 수준 pinot.broker.multistage.infer.partition.hint 설정을 덮어씀. |
브로커 수준 구성(기본 false) |
| orderedPreferredPools | 브로커 쿼리 라우팅을 위한 우선순위 서버 풀 목록. 파이프(|)로 구분된 풀 식별자(정수) 목록. canary 배포에 유용(1.4.0 도입). |
null/empty (풀 선호 없음) |
| workloadName | CPU/메모리 회계 및 워크로드 예산 집행을 위해 쿼리를 명명된 워크로드에 할당(1.4.0 도입). | null/empty (기본 워크로드에 속함) |
| isSecondaryWorkload | 쿼리를 보조 워크로드 쿼리로 표시(1.4.0 도입). | false |
| enableMultiClusterRouting | 여러 Pinot 클러스터에 걸쳐 쿼리를 라우팅하는 멀티-클러스터 쿼리(페더레이션) 활성화. MultiClusterHelixBrokerStarter 및 논리 테이블 필요. |
false (로컬 클러스터에만 실행) |
커서 페이징
| Key | 설명 | 기본 동작 |
|---|---|---|
| getCursor | true로 설정하면 전체 결과 집합 대신 커서를 반환. 큰 결과 집합에 유용. |
false (전체 결과 집합 반환) |
| cursorNumRows | 각 커서 페이지에 포함할 행 수. getCursor=true일 때만 적용. |
브로커 수준 구성 |
Explain Plan
| Key | 설명 | 기본 동작 |
|---|---|---|
| explainAskingServers | multi-stage 엔진의 explain 동작 제어. true면 서버에 세그먼트 계획을 요청. false면 논리 계획만 반환. |
브로커 수준 구성(기본 false) |
Group-By Trim
| Key | 설명 | 기본 동작 |
|---|---|---|
| minBrokerGroupTrimSize | group-by 쿼리에서 브로커 수준 그룹 트리밍 시 유지할 최소 그룹 수(SSE만). 비양수로 설정하면 브로커 수준 트림 비활성. | 브로커 수준 구성(기본 5000) |
| mseMinGroupTrimSize | multi-stage group-by 쿼리에서 중간 스테이지 집계 결과 트리밍 시 유지할 그룹 수. | 서버 수준 구성(기본 5000) |
| groupTrimThreshold | 브로커 수준 group-by 트리밍 임계값. 브로커 축소 단계에서 트림이 트리거되기 전 보유할 수 있는 최대 그룹 수 제어. | 브로커 수준 구성(기본 1000000) |
Multi-Stage 엔진 Group-By 스트리밍
| Key | 설명 | 기본 동작 |
|---|---|---|
| streamingGroupByFlushThreshold | multi-stage 엔진 GROUP BY에서 누적 그룹 수가 이 임계값에 도달하면 부분 group-by 결과를 플러시. 높은 카디널리티 GROUP BY 쿼리의 서버 메모리 사용을 제한. | 브로커 구성이 양수면 그 값, 아니면 0(비활성) |
예시: 플러시 임계값이 있는 스트리밍 Group-By
메모리 압력을 일으킬 수 있는 높은 카디널리티 GROUP BY 쿼리에 대해 스트리밍 모드를 활성화할 수 있어요.
-- Enable multi-stage engine with streaming group-by
SET useMultistageEngine = true;
SET streamingGroupByFlushThreshold = 5000;
-- Query with potentially high cardinality GROUP BY
SELECT user_id, country, COUNT(*) as event_count
FROM events
WHERE date = '2026-04-01'
GROUP BY user_id, country
LIMIT 100000;
이 예시에서 쿼리는 누적 그룹 수가 5000에 도달할 때마다 부분 group-by 결과를 플러시해 무한정 메모리 증가를 방지해요.
Multi-Stage 엔진 DISTINCT 스트리밍
| Key | 설명 | 기본 동작 |
|---|---|---|
| streamingDistinctFlushThreshold | 적격한 multi-stage DISTINCT 쿼리에서 leaf의 누적 distinct 값이 이 양의 임계값에 도달하면 플러시. 다운스트림 스테이지가 최종 중복 제거. ORDER BY 없음, leaf LIMIT > 임계값 등 조건 필요. |
브로커 기본이 양수면 그 값, 아니면 비활성 |
큰 DISTINCT limit으로 leaf가 너무 많은 값을 축적하게 될 때 이 옵션을 사용하세요.
SET useMultistageEngine = true;
SET streamingDistinctFlushThreshold = 5000;
SELECT DISTINCT user_id
FROM events
LIMIT 1000000;
이 옵션을 gRPC 스트리밍 쿼리 경로와 함께 사용하지 마세요. 그 경로에는 플러시 간 중복을 제거할 다운스트림 스테이지가 없기 때문이에요.
조인 및 윈도우 오버플로우
| Key | 설명 | 기본 동작 |
|---|---|---|
| joinOverflowMode | 조인 연산이 maxRowsInJoin을 초과할 때 동작 제어: THROW(예외 발생) 또는 BREAK(처리 중지 후 부분 결과 반환). |
THROW |
| maxRowsInWindow | 윈도우 함수 연산에 허용되는 최대 행 수. 큰 윈도우 프레임 처리 시 과도한 메모리 사용 방지. | 클러스터 구성 기본, 미설정 시 2^20 (1024*1024) |
| windowOverflowMode | 윈도우 연산이 maxRowsInWindow을 초과할 때 동작 제어: THROW 또는 BREAK. |
THROW |
Multi-클러스터 라우팅
| Key | 설명 | 기본 동작 |
|---|---|---|
| enableMultiClusterRouting | 여러 Pinot 클러스터에 걸쳐 쿼리를 라우팅하는 멀티-클러스터 쿼리(페더레이션) 활성화. MultiClusterHelixBrokerStarter 및 논리 테이블 필요. Multi-Cluster Querying 참조. |
false (로컬 클러스터에만 실행) |
브로커 프루닝
| Key | 설명 | 기본 동작 |
|---|---|---|
| useBrokerPruning | true로 설정하면 multi-stage leaf-stage 라우팅을 위한 브로커 측 세그먼트 프루닝 활성화. 쿼리 수준 useBrokerPruning이 적용 가능한 브로커 기본값을 덮어씀. |
물리 옵티마이저 경로: 브로커 구성(기본 true); 논리 플래너 적격 leaf: 브로커 구성(기본 true) |
인덱스 기반 DISTINCT
| Key | 설명 | 기본 동작 |
|---|---|---|
| useIndexBasedDistinctOperator | true일 때 적합한 인덱스 기반 DISTINCT 연산자 활성화. 단일 컬럼 SELECT DISTINCT jsonExtractIndex(...) 쿼리를 JsonIndexDistinctOperator로 라우팅하고, 사전 인코딩된 컬럼을 InvertedIndexDistinctOperator로 라우팅. |
false (비활성) |
| jsonIndexDistinctSkipMissingPath | JsonIndexDistinctOperator에만 적용. true면 누락 경로 처리를 건너뜀: 4-arg 기본값을 추가하지 않고, null 처리가 활성화되어도 NULL을 추가하지 않으며, 일부 매칭 문서가 경로를 포함하지 않아도 Illegal Json Path를 던지지 않음. |
false (4-arg 기본값 사용/있으면, 아니면 NULL 추가 또는 Illegal Json Path 발생) |
| invertedIndexDistinctCostRatio | InvertedIndexDistinctOperator의 비용 휴리스틱을 덮어씀. dictionaryCardinality * costRatio <= filteredDocCount일 때 bitmap inverted-index 경로 선택. 0으로 설정하면 필터가 한 행 이상 매칭될 때마다 bitmap 경로 강제. |
null/empty (내장 카디널리티 기반 휴리스틱 사용) |
DISTINCT 조기 종료 (Single-Stage 실행)
| Key | 설명 | 기본 동작 |
|---|---|---|
| maxRowsInDistinct | DISTINCT 쿼리에서 조기 종료 전 모든 세그먼트에서 스캔할 최대 행 수. 도달하면 스캔 중지 후 부분 결과 반환. | null/empty (제한 없음) |
| maxRowsWithoutChangeInDistinct | 새 distinct 값을 생성하지 않고 스캔할 최대 행 수. distinct 값 집합이 빠르게 수렴할 때 유용. | null/empty (제한 없음) |
| maxExecutionTimeMsInDistinct | DISTINCT 쿼리의 결합 연산자를 위한 벽시계 시간 예산(밀리초). 초과하면 부분 결과 반환. | null/empty (제한 없음) |
이 예산은 여전히 single-stage DISTINCT 실행 경로에 의해 강제돼요. multi-stage 쿼리가 DISTINCT 처리에 single-stage leaf 경로를 사용할 때 Pinot는 이제 leaf 스테이지 이유를 V2 응답에 partialResult=true와 earlyTerminationReasons로 전파해요. 네이티브 multi-stage DISTINCT 연산자는 아직 자체적으로 이러한 경계를 강제하지 않아요.
조기 종료가 있는 DISTINCT 쿼리 예시
-- 100,000행 스캔 후 중지
SELECT DISTINCT country FROM users
OPTION (maxRowsInDistinct=100000)
-- 새 distinct 값 없이 10,000행 후 중지
SELECT DISTINCT state FROM users
OPTION (maxRowsWithoutChangeInDistinct=10000)
-- 5초 실행 후 중지
SELECT DISTINCT user_id FROM events
OPTION (maxExecutionTimeMsInDistinct=5000)
-- 여러 제한 결합
SELECT DISTINCT product_id FROM orders
OPTION (maxRowsInDistinct=50000, maxRowsWithoutChangeInDistinct=5000)
이러한 조기 종료 예산 중 하나가 초과되면 Pinot는 쿼리 엔진에 따라 이유를 다르게 표시해요.
- Single-stage 응답 필드:
partialResult(boolean): 조기 종료로 결과가 부분일 때true로 설정.maxRowsInDistinctReached(boolean):maxRowsInDistinct초과 시true.maxRowsWithoutChangeInDistinctReached(boolean):maxRowsWithoutChangeInDistinct초과 시true.maxExecutionTimeInDistinctReached(boolean):maxExecutionTimeMsInDistinct초과 시true.
- Multi-stage 응답 필드(leaf 스테이지가 DISTINCT 처리를 조기 종료할 때):
partialResult(boolean):true로 설정.earlyTerminationReasons(string array):DISTINCT_MAX_ROWS,DISTINCT_MAX_ROWS_WITHOUT_CHANGE,DISTINCT_MAX_EXECUTION_TIME같은 이름 하나 이상 포함.
조기 종료가 있는 SSE 응답 예시
{
"resultTable": {
"dataSchema": {
"columnNames": ["country"],
"columnDataTypes": ["STRING"]
},
"rows": [
["USA"],
["Canada"],
["Mexico"]
]
},
"numDocsScanned": 100000,
"numEntriesScannedInFilter": 100000,
"numEntriesScannedPostFilter": 100000,
"totalDocs": 10000000,
"numSegmentsQueried": 10,
"numSegmentsProcessed": 6,
"partialResult": true,
"maxRowsInDistinctReached": true,
"maxRowsWithoutChangeInDistinctReached": false,
"maxExecutionTimeInDistinctReached": false,
"timeUsedms": 245
}
전파된 DISTINCT 조기 종료가 있는 MSE 응답 예시
{
"resultTable": {
"dataSchema": {
"columnNames": ["country"],
"columnDataTypes": ["STRING"]
},
"rows": [
["USA"],
["Canada"],
["Mexico"]
]
},
"partialResult": true,
"earlyTerminationReasons": ["DISTINCT_MAX_ROWS"]
}